From cbb5d08a0c934198a334b7cfacf8ba62253c7ba9 Mon Sep 17 00:00:00 2001 From: mostlikely4r Date: Thu, 5 Jun 2025 12:37:16 +0200 Subject: [PATCH] Initial commit --- Construction Adv Launcher.bat | 53 + Construction Dedicated Server.bat | 3 + Construction Offline Practice And LAN.bat | 3 + Construction Online Listen Server.bat | 3 + ConstructionPreferences.cs | 7 + Credits.txt | 56 + DSO Remover.bat | 30 + Version-history.txt | 1108 +++++ readme.txt | 86 + scripts/ConstructionGame.cs | 100 + scripts/Function Library R3.txt | 275 ++ scripts/JTLmeteorStorm.cs | 196 + scripts/MPM/MPM.cs | 795 +++ scripts/MPM/MPM_AE.cs | 705 +++ scripts/MPM/MPM_Blast.cs | 1635 +++++++ scripts/MPM/MPM_Launch.cs | 185 + scripts/MPM/MPM_base.cs | 2320 +++++++++ scripts/MPM/Mpm_BE.cs | 272 ++ scripts/MPM/Mpm_SE.cs | 766 +++ scripts/MPM/Mpm_TE.cs | 193 + scripts/MPM/Mpm_VE.cs | 205 + scripts/MPM/Nuclear_blast.cs | 1356 ++++++ scripts/MPM/Nuke_Cannon.cs | 2585 ++++++++++ scripts/MTC_ai.cs | 1227 +++++ scripts/MTC_core.cs | 1482 ++++++ scripts/MTC_eWeap.cs | 531 ++ scripts/MTC_level.cs | 41 + scripts/MTC_weap.cs | 1334 +++++ scripts/OptionsDlg.cs | 2763 +++++++++++ scripts/TR2Game.cs | 31 + scripts/admin.cs | 612 +++ scripts/chatCommands.cs | 86 + scripts/client.cs | 2132 ++++++++ scripts/controlDefaults.cs | 1606 +++++++ scripts/dEffects.cs | 284 ++ scripts/damageTypes.cs | 754 +++ scripts/deathMessages.cs | 420 ++ scripts/defaultGame.cs | 5080 ++++++++++++++++++++ scripts/deployables.cs | 2075 ++++++++ scripts/do_not_delete/Dfunctions.cs | 1431 ++++++ scripts/do_not_delete/loadscreen.cs.dso | Bin 0 -> 3195 bytes scripts/editor.cs | 113 + scripts/expertLibraries.cs | 148 + scripts/forceField.cs | 290 ++ scripts/functions.cs | 1034 ++++ scripts/gameBase.cs | 147 + scripts/hazard.cs | 134 + scripts/hfunctions.cs | 106 + scripts/hud.cs | 1929 ++++++++ scripts/inventory.cs | 922 ++++ scripts/inventoryHud.cs | 1503 ++++++ scripts/ion.cs | 1012 ++++ scripts/item.cs | 1086 +++++ scripts/libraries.cs | 362 ++ scripts/message.cs | 422 ++ scripts/nerf.cs | 121 + scripts/pack.cs | 122 + scripts/packs/AntiNuketurret.cs | 724 +++ scripts/packs/Effectpacks.cs | 1806 +++++++ scripts/packs/blastfloor.cs | 242 + scripts/packs/blastwall.cs | 271 ++ scripts/packs/blastwwall.cs | 225 + scripts/packs/cratepack.cs | 248 + scripts/packs/deconExamples.cs | 51 + scripts/packs/decorationpack.cs | 376 ++ scripts/packs/discturret.cs | 257 + scripts/packs/door.cs | 330 ++ scripts/packs/doorbu.cs | 322 ++ scripts/packs/energizer.cs | 385 ++ scripts/packs/escapepodpack.cs | 393 ++ scripts/packs/forcefieldpack.cs | 518 ++ scripts/packs/generator.cs | 145 + scripts/packs/gravityfieldpack.cs | 344 ++ scripts/packs/jumpad.cs | 176 + scripts/packs/largeInventory.cs | 123 + scripts/packs/largeSensor.cs | 127 + scripts/packs/laserturret.cs | 193 + scripts/packs/lightpack.cs | 273 ++ scripts/packs/logoprojectorpack.cs | 238 + scripts/packs/mediumSensor.cs | 127 + scripts/packs/missilerackturret.cs | 455 ++ scripts/packs/mspine.cs | 282 ++ scripts/packs/repairpack.cs | 657 +++ scripts/packs/satchelCharge.cs | 758 +++ scripts/packs/solarpanel.cs | 143 + scripts/packs/spine.cs | 285 ++ scripts/packs/switch.cs | 273 ++ scripts/packs/telepadpack.cs | 564 +++ scripts/packs/treepack.cs | 258 + scripts/packs/tripwire.cs | 393 ++ scripts/packs/turretpack.cs | 141 + scripts/packs/vehiclepad.cs | 764 +++ scripts/player.cs | 3693 ++++++++++++++ scripts/power.cs | 358 ++ scripts/prison.cs | 310 ++ scripts/projectiles.cs | 683 +++ scripts/saveBuilding.cs | 841 ++++ scripts/server.cs | 2797 +++++++++++ scripts/serverCommanderMap.cs | 373 ++ scripts/skywrite.cs | 606 +++ scripts/solitudeBlock.cs | 117 + scripts/staticShape.cs | 1576 ++++++ scripts/station.cs | 1283 +++++ scripts/truPhysics.cs | 238 + scripts/turret.cs | 382 ++ scripts/turrets/indoorDeployableBarrel.cs | 328 ++ scripts/turrets/outdoorDeployableBarrel.cs | 254 + scripts/vehicles/serverVehicleHud.cs | 430 ++ scripts/vehicles/vehicle.cs | 2131 ++++++++ scripts/vehicles/vehicle_artillery.cs | 780 +++ scripts/vehicles/vehicle_bomber.cs | 997 ++++ scripts/vehicles/vehicle_escapepod.cs | 138 + scripts/vehicles/vehicle_havoc.cs | 226 + scripts/vehicles/vehicle_mpb.cs | 304 ++ scripts/vehicles/vehicle_shrike.cs | 344 ++ scripts/vehicles/vehicle_superHavoc.cs | 189 + scripts/vehicles/vehicle_superWildcat.cs | 146 + scripts/vehicles/vehicle_tank.cs | 686 +++ scripts/vehicles/vehicle_wildcat.cs | 222 + scripts/weapTurretCode.cs | 927 ++++ scripts/weapons.cs | 384 ++ scripts/weapons/constructionTool.cs | 1168 +++++ scripts/weapons/dragonmissile.cs | 547 +++ scripts/weapons/modifiertool.cs | 707 +++ scripts/weapons/nerfBallLauncher.cs | 288 ++ scripts/weapons/nerfGun.cs | 250 + scripts/weapons/superChaingun.cs | 259 + updates.txt | 279 ++ 128 files changed, 82385 insertions(+) create mode 100644 Construction Adv Launcher.bat create mode 100644 Construction Dedicated Server.bat create mode 100644 Construction Offline Practice And LAN.bat create mode 100644 Construction Online Listen Server.bat create mode 100644 ConstructionPreferences.cs create mode 100644 Credits.txt create mode 100644 DSO Remover.bat create mode 100644 Version-history.txt create mode 100644 readme.txt create mode 100644 scripts/ConstructionGame.cs create mode 100644 scripts/Function Library R3.txt create mode 100644 scripts/JTLmeteorStorm.cs create mode 100644 scripts/MPM/MPM.cs create mode 100644 scripts/MPM/MPM_AE.cs create mode 100644 scripts/MPM/MPM_Blast.cs create mode 100644 scripts/MPM/MPM_Launch.cs create mode 100644 scripts/MPM/MPM_base.cs create mode 100644 scripts/MPM/Mpm_BE.cs create mode 100644 scripts/MPM/Mpm_SE.cs create mode 100644 scripts/MPM/Mpm_TE.cs create mode 100644 scripts/MPM/Mpm_VE.cs create mode 100644 scripts/MPM/Nuclear_blast.cs create mode 100644 scripts/MPM/Nuke_Cannon.cs create mode 100644 scripts/MTC_ai.cs create mode 100644 scripts/MTC_core.cs create mode 100644 scripts/MTC_eWeap.cs create mode 100644 scripts/MTC_level.cs create mode 100644 scripts/MTC_weap.cs create mode 100644 scripts/OptionsDlg.cs create mode 100644 scripts/TR2Game.cs create mode 100644 scripts/admin.cs create mode 100644 scripts/chatCommands.cs create mode 100644 scripts/client.cs create mode 100644 scripts/controlDefaults.cs create mode 100644 scripts/dEffects.cs create mode 100644 scripts/damageTypes.cs create mode 100644 scripts/deathMessages.cs create mode 100644 scripts/defaultGame.cs create mode 100644 scripts/deployables.cs create mode 100644 scripts/do_not_delete/Dfunctions.cs create mode 100644 scripts/do_not_delete/loadscreen.cs.dso create mode 100644 scripts/editor.cs create mode 100644 scripts/expertLibraries.cs create mode 100644 scripts/forceField.cs create mode 100644 scripts/functions.cs create mode 100644 scripts/gameBase.cs create mode 100644 scripts/hazard.cs create mode 100644 scripts/hfunctions.cs create mode 100644 scripts/hud.cs create mode 100644 scripts/inventory.cs create mode 100644 scripts/inventoryHud.cs create mode 100644 scripts/ion.cs create mode 100644 scripts/item.cs create mode 100644 scripts/libraries.cs create mode 100644 scripts/message.cs create mode 100644 scripts/nerf.cs create mode 100644 scripts/pack.cs create mode 100644 scripts/packs/AntiNuketurret.cs create mode 100644 scripts/packs/Effectpacks.cs create mode 100644 scripts/packs/blastfloor.cs create mode 100644 scripts/packs/blastwall.cs create mode 100644 scripts/packs/blastwwall.cs create mode 100644 scripts/packs/cratepack.cs create mode 100644 scripts/packs/deconExamples.cs create mode 100644 scripts/packs/decorationpack.cs create mode 100644 scripts/packs/discturret.cs create mode 100644 scripts/packs/door.cs create mode 100644 scripts/packs/doorbu.cs create mode 100644 scripts/packs/energizer.cs create mode 100644 scripts/packs/escapepodpack.cs create mode 100644 scripts/packs/forcefieldpack.cs create mode 100644 scripts/packs/generator.cs create mode 100644 scripts/packs/gravityfieldpack.cs create mode 100644 scripts/packs/jumpad.cs create mode 100644 scripts/packs/largeInventory.cs create mode 100644 scripts/packs/largeSensor.cs create mode 100644 scripts/packs/laserturret.cs create mode 100644 scripts/packs/lightpack.cs create mode 100644 scripts/packs/logoprojectorpack.cs create mode 100644 scripts/packs/mediumSensor.cs create mode 100644 scripts/packs/missilerackturret.cs create mode 100644 scripts/packs/mspine.cs create mode 100644 scripts/packs/repairpack.cs create mode 100644 scripts/packs/satchelCharge.cs create mode 100644 scripts/packs/solarpanel.cs create mode 100644 scripts/packs/spine.cs create mode 100644 scripts/packs/switch.cs create mode 100644 scripts/packs/telepadpack.cs create mode 100644 scripts/packs/treepack.cs create mode 100644 scripts/packs/tripwire.cs create mode 100644 scripts/packs/turretpack.cs create mode 100644 scripts/packs/vehiclepad.cs create mode 100644 scripts/player.cs create mode 100644 scripts/power.cs create mode 100644 scripts/prison.cs create mode 100644 scripts/projectiles.cs create mode 100644 scripts/saveBuilding.cs create mode 100644 scripts/server.cs create mode 100644 scripts/serverCommanderMap.cs create mode 100644 scripts/skywrite.cs create mode 100644 scripts/solitudeBlock.cs create mode 100644 scripts/staticShape.cs create mode 100644 scripts/station.cs create mode 100644 scripts/truPhysics.cs create mode 100644 scripts/turret.cs create mode 100644 scripts/turrets/indoorDeployableBarrel.cs create mode 100644 scripts/turrets/outdoorDeployableBarrel.cs create mode 100644 scripts/vehicles/serverVehicleHud.cs create mode 100644 scripts/vehicles/vehicle.cs create mode 100644 scripts/vehicles/vehicle_artillery.cs create mode 100644 scripts/vehicles/vehicle_bomber.cs create mode 100644 scripts/vehicles/vehicle_escapepod.cs create mode 100644 scripts/vehicles/vehicle_havoc.cs create mode 100644 scripts/vehicles/vehicle_mpb.cs create mode 100644 scripts/vehicles/vehicle_shrike.cs create mode 100644 scripts/vehicles/vehicle_superHavoc.cs create mode 100644 scripts/vehicles/vehicle_superWildcat.cs create mode 100644 scripts/vehicles/vehicle_tank.cs create mode 100644 scripts/vehicles/vehicle_wildcat.cs create mode 100644 scripts/weapTurretCode.cs create mode 100644 scripts/weapons.cs create mode 100644 scripts/weapons/constructionTool.cs create mode 100644 scripts/weapons/dragonmissile.cs create mode 100644 scripts/weapons/modifiertool.cs create mode 100644 scripts/weapons/nerfBallLauncher.cs create mode 100644 scripts/weapons/nerfGun.cs create mode 100644 scripts/weapons/superChaingun.cs create mode 100644 updates.txt diff --git a/Construction Adv Launcher.bat b/Construction Adv Launcher.bat new file mode 100644 index 0000000..574ab53 --- /dev/null +++ b/Construction Adv Launcher.bat @@ -0,0 +1,53 @@ +@echo OFF +echo Construction Mod 0.70 +echo Advanced Mod Loader +echo. +echo Please choose options below to launch server: +echo. +echo Options: +echo 1) Launch Online Dedicated Server (Ispawn). +echo 2) Launch Online Dedicated Server. +echo 3) Launch Offline Dedicated Server (Ispawn). +echo 4) Launch Offline Dedicated Server. +echo 5) Launch Online Listen Server. +echo 6) Launch Offline Listen Server. +echo 7) Exit. +set /p Input=Press enter after selection (1-7): +if %Input%==7 goto exit +set /p RemDSO=Would you like to remove all DSOs from your Tribes 2 install? (y/n): +cd .. +if %RemDSO%==y del /s /q *.dso +if %Input%==1 goto NDI +if %Input%==2 goto ND +if %Input%==3 goto FDI +if %Input%==4 goto FD +if %Input%==5 goto NL +if %Input%==6 goto FL + +goto exit + +:NDI +start ispawn.exe 28000 Tribes2.exe -dedicated -mod Construction +goto exit + +:ND +start Tribes2.exe -dedicated -mod Construction +goto exit + +:FDI +start ispawn.exe 28000 Tribes2.exe -nologin -dedicated -mod Construction +goto exit + +:FD +start Tribes2.exe -nologin -dedicated -mod Construction +goto exit + +:NL +start Tribes2.exe -online -mod Construction +goto exit + +:FL +start Tribes2.exe -nologin -mod Construction +goto exit + +:exit \ No newline at end of file diff --git a/Construction Dedicated Server.bat b/Construction Dedicated Server.bat new file mode 100644 index 0000000..1158e4d --- /dev/null +++ b/Construction Dedicated Server.bat @@ -0,0 +1,3 @@ + cd ..\ +start ispawn.exe 28000 Tribes2.exe -dedicated -mod Construction + exit \ No newline at end of file diff --git a/Construction Offline Practice And LAN.bat b/Construction Offline Practice And LAN.bat new file mode 100644 index 0000000..5e7818a --- /dev/null +++ b/Construction Offline Practice And LAN.bat @@ -0,0 +1,3 @@ + cd ..\ +start Tribes2.exe -nologin -mod Construction +exit \ No newline at end of file diff --git a/Construction Online Listen Server.bat b/Construction Online Listen Server.bat new file mode 100644 index 0000000..8fb9c38 --- /dev/null +++ b/Construction Online Listen Server.bat @@ -0,0 +1,3 @@ + cd ..\ +start Tribes2.exe -online -mod Construction +exit \ No newline at end of file diff --git a/ConstructionPreferences.cs b/ConstructionPreferences.cs new file mode 100644 index 0000000..e97167d --- /dev/null +++ b/ConstructionPreferences.cs @@ -0,0 +1,7 @@ +//Construction 0.70 Server Configuration File + +//Logging: +$Construction::Logging::EchoChat = 1; +$Construction::Logging::LogConnects = 1; //disconnects too +$Construction::Logging::LogChat = 1; + diff --git a/Credits.txt b/Credits.txt new file mode 100644 index 0000000..181e5d0 --- /dev/null +++ b/Credits.txt @@ -0,0 +1,56 @@ +Don't forget to add yourself to this list.. :D + +**JackTL** +For: +Maintaining mod from v50a. + +**Construct** +For: +providing main idea. +still providing great ideas to keep the mod going. +Testing and tweacking. +lot's of additions and coding help. +The neat installer. + +**Tutorial makers** +For: +Making tutorials.. duh.. + +**Lucid** +For: +Helping me with the code. +providing me with a great decontruct gun. +the neat looking loadscreen. +For being willing to help me with lots of stuff + +**Badshot** +For: +Taking the time to help me with some nasty bugs. +Knowing alot for tribes2 stuff.. and being willing to share it. +Helping all those other modders. + +**DynaBlade** +For: +His Awesome function librarys + +**T2CC** +For: +Their great forum and putting all that coding power at your very fingertips. + +**Child_Killer** +For: +Providing code that was posted before my time and being a great help so far. + +**All those who I fogot to mention sofar** +For: +Whatever they did to help this mod. + +**All those who wanted to help but couldn't** +Remember, it's the thought that counts ;) + + +**By** +Mostlikely, + +I don't need any credit for this mod, it was created for the people who want to play it (which includes me) +Feel free to use any stuff from this mod or ask me about it if you can't extract it somehow. diff --git a/DSO Remover.bat b/DSO Remover.bat new file mode 100644 index 0000000..18d11e1 --- /dev/null +++ b/DSO Remover.bat @@ -0,0 +1,30 @@ +@echo off +color 2f +cls +echo; +echo; +echo ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +echo º 0.70 DSO Remover º +echo ÌÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͹ +echo º This DOS batch file will remove those pesky dso's from º +echo º your Tribes 2 installation. Regardless of where it is. º +echo ÌÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͹ +echo º Remove all DSO files(not flagged as read only) from º +echo º Tribes 2 directory by pressing enter. º +echo ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ +echo; +echo; +pause +cd .. +del /s /q *.dso +cls +echo; +echo; +echo ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +echo º Success! º +echo º º +echo º All dso's from Tribes 2 have been removed. º +echo ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ +echo; +echo; +pause \ No newline at end of file diff --git a/Version-history.txt b/Version-history.txt new file mode 100644 index 0000000..999af6c --- /dev/null +++ b/Version-history.txt @@ -0,0 +1,1108 @@ +Latest changes added at top. To read chronologically, +start from bottom. + +**********************0.69 Alpha********************** + +-Didn't update the version history all that good for + certain reasons. + +-Construction Tool will now tell owner client id and + object id when admins read it's power state. + +-Added Transport Missile Gun for traveling great distances + quickly without much fuss. Custom travel time settable. + +-Added 4 'effect' packs. + All use expert and pack setting modes. + >Emitter pack, includes all particle emitters in t2. + >Audio pack, includes all audio effects in t2. + (so a few crap ones too). + >Pack Dispenser pack, includes most packs/weapons/ammo. + >Detonation pack, enables along with satchel charges. + fxGroup, fx_emitters, fx_audio, fx_packs ".delete();" + will remove the effects spawned by the first 3 packs. + +-Added Deployable vehicle pad. + Requires a construction piece surface larger than 20x20 meters. + 2 step deploy: 1-Pad 2-station. + +-Added Multi purpose missile lauchers to the mpb. + which can be enabled with "$mpm::nukempb = 1;" + +** + +-Fixed misc. other stuff. + +-Fixed tossing grenade/mine when toggling Construction + Tool or Super Chaingun grenade/mine modes too quickly. + +-Fixed meteors damaging items behind walls. + +-Fixed server always starting with Cascade mode enabled. + +-Repair Pack should now let players repair themselves + while inside Construction buildings.. + +**********************0.68 Alpha********************** + +-Cascade mode and Vehicles on/off options are now separate + from Purebuild mode toggle, and saved separately in server + prefs file. + +-Repair Kit now works in non-Purebuild mode, with Expert + mode on. + +-Added admin menu item to toggle Invincible Deployables + mode. + +-Added Invincible Deployables mode. + +-When Invincible Armors mode is on, would-be damage is + displayed as a waypoint with a percentage of max damage + for that armor. Team damage is not shown if there are + multiple teams. + +-Added admin menu to remove all orphaned deployables + in the mission. This includes all deployables where + the owner is no longer in the game. + +-Added GUID owner tracking. Owner status is now saved + with buildings. + + NB: GUID is not used by T2 in Solo/LAN games. + +-When a player is found spamming, anything deployed by + that player within the last 15 seconds is disassembled. + Can be changed with host variable. + +-Smartened up turrets multiple target selection code. + +-Fixed Missile Rack Turret's dumbfire/seeker mode not + saving. + +**********************0.67 Alpha********************** + +-Fixed Force Field damage handling with team damage off. + +-Construction Tool will now tell you who owns a piece + when you read it's power state. + +-Construction Mod updated to Tribes 2 v0.25034.0.0 + +-Added "dumbfire" and "seeking" modes to Missile Rack + Turret pack Expert mode options. "seeking" mode drains + more energy. + +-Added Missile Rack Turret pack. This turret needs power + to function. + +-Added "only transmit" and "only receive" modes to Telepad + Expert mode options. + +-Added "Timed turn off" and "Timed turn on" modes to + Tripwire pack Expert mode options. + +-Added "team only" and "any team" modes to Telepad + Expert mode options. + +-Added scale options to Tree pack Expert mode options. + +-Added new underground code. + +-Changed shape of Decoration pack. + +-Added new billboard shapes to Decoration pack. + +-Fixed Pulse Sensor not doing "deploy" anim when loaded. + +-Added admin menu item to enable/disable Underground mode. + +-Added "Only turn on" and "Only turn off" modes to + Tripwire pack Expert mode options. + +-Escape Pod should no longer be usable as an explosive + siege machine. :P + +-Added boost power setting to Escape Pod pack. + +-Escape Pods should no longer launch players underground. + +**********************0.666 Alpha********************** + +-Added Escape Pod pack. + +-Added Field mode to Tripwire pack. + +-Admins can now use Construction Tool on objects even if + they are not on the same team. + +-Admins can now rotate objects even if Only Owner + Rotate is enabled. + +-Added code to prevent players from crashing server by + falling from great height. + +-Walls/pads can now be deployed properly on the thin side of + other walls. + +-Added host variable $Host::NoAnnoyingVoiceChatSpam" to + let hosts prevent players from using the "null" voice + to spam sound effects. :P + +-Included Editor fix (stops it from enabling cheats) in + Construction Mod, since so many people like to play with + it while hosting. :p + +-Added Tripwire pack. Extra options are available in + Expert mode. Usage is similar to the Switch pack. + +-Fixed problem with auto-adjusting Medium Support Beam + scaling weird when deploying on terrain. + +-Added Expert mode sizes to Medium Support Beam. + +-New server variable "$Host::StationHoldTime" holds the + time in milliseconds that players are held when using + an inventory station. + +-Admins and Super Admins can now use power frequencies + 1 to 50, instead of the normal 1 to 40. + +-Fixed Satchel Charge, again. Oops! + +**********************0.65 Alpha********************** + +-Construction Mod updated to Tribes 2 v0.25026.0.0 + +**********************0.64 Alpha********************** + +-Added new Ion effects. + +-Updated Force Field settings. This should hopefully give + some players higher FPS. + +-Added delayed reset mode to Switch, usable in Expert mode. + +-Added vote menu to enable/disable Expert mode. + +-Included new bat file, "JTLdelDSO.bat", in archive. + + This batch file deletes all *.dso files in "..\base" and + the current directory (should be the Construction folder), + and all subfolders. + + NB: It does not ask for confirmation before deleting files. + Use at your own risk. Tested under WinXP only. + + Please use only if the other DSO deleters do not work + for you. + +-An object will now be destroyed if it is too damaged + when deconstructed. + +-Added message broadcast when a player takes control of + an object. + +-Reverted Satchel Charge pack image back to normal. Oops! + +**********************0.63 Alpha********************** + +-Lots of small fixes. + +-Changed how spam is punished. + +-Added new effects for deploying and deconstructing objects. + +-Added keyboard mappings for cycling pack settings forward, + backward, fast forward and fast backward. + Players must run the mod client-side to take advantage + of the new key bind options. + +-Added keyboard mappings for doing a jig, laying down, + heart attack and sucker punched. + Players must run the mod client-side to take advantage + of the new key bind options. + +-Added admin menu item to enable/disable "Only Owner + Cubic Replace mode", which will only let the creator of + an object cubic replace it. + +-Added admin menu item to enable/disable Cascade mode. + +-Made cascading deployables a mode separate from Purebuild + mode. + +-Added an easier function to relight mission client-side. + Clients can enter "reLightMission();" in console to light + their mission. + +-Added new "Builder Pack" entry to Inventory Hud. This + now contains most of the deployable packs. + +-Added admin menu item to enable/disable MTC mode. + +-Added MTC mode. + +-Changed Jump Pad deploy code. + +-Changes in Deployable Light. Any Light saved with v0.62a + can not be deconstructed when loaded in 0.63a. + +-Made Construction Mod packs available in inventory hud + again, at the cost of turret barrel packs. + +-Added Ion mode to Super Chaingun, using same controls as + Construction Tool. + +-Added light source to Hazard mode meteors. + +-Admins now get Super Chaingun when using Deployed Inventory + Station. + +-Telepad can no longer be rotated with Advanced Rotate. + +-Made Team Damage vote menu available in single-team games. + +-Deployed Camera and Prison Camera can now be controlled + in Purebuild mode. + +-Added key bind for selecting Jump Pad. + +**********************0.62 Alpha********************** + +-Fixed problem with Telepad not working past 10km altitude. + New limit is 100km. + +-Added keyboard mappings for sitting and squatting. + Players must run the mod client-side to take advantage + of the new key bind options. + +-Admins can now deconstruct objects even if Only Owner + Deconstruct is enabled. This includes cascade + deconstruction. + +-Added "wooden pad" to Light Support Beam pack. + +-Vehicles can now pass through disabled force fields. + +-Deconstructed objects' packs now appear at the end of + the Construction Tool's beam. + +-Added Deployable Light to savebuilding.cs. + +-Added Light Pack. + +-Fixed Switches affecting objects not on their own team. + +-Fixed problem with vehicle counts being off after + calling pureVehicles(). + +-Added page cycling to vehicle selection hud. + +-Fixed server-side weapon reticles. + +-Changed Energizer explosion effect. + +-Energizer can not be deployed within 30 meters of an + enemy object. + +-Added Deployable Camera to savebuilding.cs. + +-Pure armor can now use Camera grenade. + +-Medium Support Beam ring options reversed. Rings can + now be enabled in Expert mode. + +-Construction Tool will now tell you who owns a piece if + you try to deconstruct a piece not belonging to you and + Only Owner Deconstruct is enabled. + +-If Purebuild mode is off, Satchel Charge warning messages + are only sent to the player's team. + +-Tweaked Energizer. It now only affects Heavy armor, + gives less recharge boost, and is destroyed more easily. + +-Generator now takes 100% of damage from Force Field, + not just 75%. + +-Medium armor can now carry barrel packs again. + +-Added Deployable Turret Base, Clamp Turret and Landspike + Turret to savebuilding.cs. + +-Deployed turrets no longer damage deployables on their + own team. + +-Fixed problem with Light Walkway modes in Expert mode. + +-Max vehicles per team reset to base values for + non-Purebuild mode. + +-Added base Pulse Sensor and Motion Sensor deployables + to savebuilding.cs. + +-Added Super Wildcat and Super Havoc vehicles. Only + available in Purebuild mode. + +-Note that in some cases, the pack-list may be too long + to display properly in the inventory selection hud. + The new QuickPack entries should alleviate this problem + until a fix is done. + +-Added QuickPack entries for most Construction packs. + Players must run the mod client-side to take advantage + of the new key bind options. + +-Made Construct come out of his box for a while. + +-Spider Clamp turret can now be deployed on most + Construction deployables. + +-Turrets can no longer be controlled in Purebuild mode, except + by Admin. + +-Pure armor can now carry Flare grenade, turret barrel packs, + Base Turret pack, Pulse and Motion sensor packs, Clamp + and Landspike turret packs. + +-Fixed cubic replace exploit. + +-Added new Medium Sensor and Large Sensor to savebuilding.cs. + +-Added new Medium Sensor and Large Sensor packs. + +**********************0.61 Alpha********************** + +-Many small fixes. + +-Switches are now half the size of normal base switches. + +-Reverted all vehicles to base values. + +-Added "Construction" gametype script for Construction + missions. + +-Added warning sound to deployable spam warning message. + +-Reworked part of generator object handling in savebuilding.cs. + +-Force Field slow-down can now be toggled in Expert mode. + +-Construction Tool now overrides Grenade and Mine + release - not the other way around. + +-Force Field now kills any players caught in it when + powering up. + +-Medium Floor can now only be deployed on terrain, interior + and Medium Floor shapes in non-Purebuild mode. This change + only applies to Purebuild mode when Hazard mode is on. + +-Construction Tool, "Read power frequency" mode renamed + to "Read power state" mode. It now shows how many power + sources are powering an item as well as it's power frequency. + +-Deployables that require power from Generator objects + now have a greater recharge rate when when powered by + more than one Generator. + +-Added colours to admin menu. + +-Added admin menu item to enable/disable Hazard mode. + +-Added Hazard mode for hazardous construction. + +**********************0.60 Alpha********************** + +-A short list of server options now appear in players + Message Hud on when they join the game. + +-Added Switch pack. Touching it will toggle on or off + all power objects in range, that are on the same team + and same power frequency. Beacon key sets range. + +-Fixed deployed item count being wrong after destroying + a large cluster of pieces. + +-Significantly reduced lag when cascading large structures. + +-Solar Panel now face upwards when deployed on + slopes. + +-Added Logo Projector pack. The logo is selected with beacon + key. In non-Purebuild mode, only the player's team logo is + available. The projector needs power to operate. + +-Added Decoration pack with 12 different decoration items. + Any object deployed on statue base will snap to the top, + in center, and upright. Any statue deployed on statue + base will snap to statue base rotation as well. + +-Inventory stations will no longer snap player to center + if used underground. + +-Advanced Rotate will no longer rotate an object entirely + underground. + +-Rotate functions are no longer available in Construction + Tool in non-Purebuild mode. + +-Generator and Solar Panel objects now store their on/off + state when saved. + +**********************0.59 Alpha********************** + +-Fixed Telepad teleporting underground exploit. + +-Added $ModVersion and $ModCredits global variables to hold + mod version and credits strings. Modders re-modding + Construction Mod should change the these strings at top of + "server.cs". + +-Saved buildings now store the version of Construction Mod + their are saved with. + +-Added admin menu to load saved buildings. To stay server- + side, this menu is listed under "Change the Mission", as + " - Load Building File - " game type. File menu will list + last 10 auto-saved files provided they are in an unbroken + sequence from 0 and up, and also any "*.cs" files stored + under "Buildings/Admin/*". + +-Changed shape of Telepad and reworked Telepad code. Added + new power up effect and sounds. + + Note: All Telepads in saved buildings from previous versions + will be broken. This can be fixed by either turning them + upside-down by hand or redeploying them. + +-Generator and Solar Panel objects now show their power + frequency and switch state when looked at. + +-Added admin menu to re-evaluate power for all deployables + in the mission. This is needed in case power system becomes + corrupted, after loading a building for example. + +-Added admin menu to remove all deployables in the mission + without power. This is intended as an aid in removing spam. + Generator and Solar Panel objects are listed in Commander Hud, + and any other deployables can be removed with this function. + + Note that this function only removes objects outside the + "power zone" of any power object. No checks for power frequency + or team is made. It is intended as a tool to remove spam + outside "populated" areas only. + +-Added Power Panagement mode to Construction Tool. Also fixed + timing issues with the different Tool modes. + +-Added power frequencies for generators and powered objects. + Power frequency is set by either using beacon key before + deploying generator object, or using Power Panagement mode of + Construction Tool. Any powered object deployed by player + will use that frequency until power frequency is changed, + or player dies. + +-Players will no longer be allowed to spawn with "illegal" + equipment if they have a non-existent armor in favourites. + +-Changed vote for "No Time Limit" to set time to one week, + instead of 200 minutes. + +-Fixed issues with players being unable to use weapons + and backpacks if the inventory station they are in is + deconstructed. + +-Armor limitations enforced. For non-admins, only Pure + armor is available in Purebuild mode, and Pure armor is + not available in non-Purebuild mode. + +-Fixed issues with Advanced Rotate list in Construction + Tool. + +-Fixed Energizer code not working right when throwing + Energizer pack, or leaving Energizer coverage while + carrying Energizer pack. + +-When rotating a Large Inventory Station, the trigger + object is now moved as well. + +-Rewrote much of Telepad code. Added teleport + emitter. + +-Fixed Telepad pack not showing in hud. + +-Force Field and Gravity Field will now disappear + instantly after being deployed if there is no power + source available. Already deployed fields will power + down, but not disappear, if they lose power. + +-Added new Generator and Solar Panel to savebuilding.cs. + +-Added new Generator and Solar Panel packs. Force Field, + Gravity Field, Large Inventory Station and shielded + objects now require power to operate. Generator powers + items within a 100 meter radius. Solar Panel powers items + within a 50 meter radius. + + Deployable Generator and Solar Panel do not power normal + base objects, and normal base generators do not power + deployables. + + When a Force Field or Gravity Field is damaged, it will absorb + 25 percent of the damage and evenly distribute the remaining + 75 percent among Generator and Solar Panel units that power it, + draining shields and causing damage. + +-Tree pack can now be deployed close to another Tree, or on + another Tree. Most deployables can be deployed on it. The same + goes for Crate pack as well. + +-Added new Crate pack with 13 different decorative crates. + +-Fixed Construction Tool creating a pack even if cascade + deconstruction failed. + +-Fixed Force Field and Gravity Field objects not rotating + properly with the Construction Tool. + +-Fixed Deployable Base Turret pack not showing in hud. + +-Cleaned up Energizer code. + + Note: All saved buildings that contain energizers must + change all instances of "DeployedVampire" to + "DeployedEnergizer" to load the energizers. + +-Cascading deconstruction now deconstructs objects + normally, without exploding them. + +-Player sensors reverted to base values. + +-Fixed Medium Floor pack not showing in hud. + +**********************0.58 Alpha********************** + +-10000 meter Light Support Beam in Expert mode changed + to 4000 meters. + +-Trees will now align with slope of the surface they are + deployed on. + +-Tree pack now has 14 different tree types, selectable + with beacon key. + +-Fastfields removed from Gravity Field pack because they + could be used to hang server. + +-Pulse and Motion sensors are now available for Medium + and Heavy armors, like in base Tribes 2. + +-Light Walkway double width or height can now be toggled + in Expert mode. + +-Fixed Medium Support Beam pack not showing in hud. + +-Telepads now show their frequency setting when looked at. + +-Player using Telepad should now only hear one teleport + sound. + +-Added 4 meter Medium Support Beam. + +-Turrets will no longer fire automatically in Purebuild + mode. + +**********************0.57 Alpha********************** + +-Medium Support Beam rings can now be disabled in + Expert mode. + +-Inventory Stations now deploy correctly on flat surfaces, + facing the player. + +-Telepad's beam shortened to fit under 4m ceilings. + +-Many internal changes and fixes. + +-Saved/loaded upside-down deployed Station Inventories + released the player wrongly. Fixed. + +-Fixed the way force field and gravity field padding was + added in cubic replace mode. + +-Updated the kind of packs different armors can carry. + +-Added new gravity fields to savebuilding.cs. + +-Added new Gravity Field pack with options. Field auto + adjusts up to 500m "upwards", and can be deployed at + any angle. + +-Force Fields will now deconstruct properly when cascade + option is enabled. + +**********************0.56 Alpha********************** + +-Deployables now link to the center of the surface if + they are larger than the surface. + +-Medium Support Beams now have 7 options: 1 meter, + 8 meter, 40 meter, 160 meter, auto adjusting, no rings + and platformrings. The last two modes are auto adjusting. + +-Telepads and Large Inventory Stations should now place + the player correctly even when placed upside down. + +-Jump Pads are now directional. Place them on walls for + horizontal jumps. + +-Deployables that deconstruct to packs should no longer + spawn inside walls if the deployable was deployed + upside down or against a wall. + +-Added boost strength options to Jump Pad. + +-Number of deployable Force Fields per team increased + to 100. + +-"Remove All Duplicate Deployables" and "Remove All + Deployables In Mission" admin options will no longer + function until the previous operation has finished. + +-Added admin menu to remove all duplicate deployables + in the mission. + +-Light Walkway now has a "No-flicker" mode selectable + in Expert mode. This micro-adjusts the position of + the Walkway to avoid Z-buffer flicker. + +-Blast Wall now has 4 options. Deploy from inside, + from outside, in frame, or "full protection". + A "Multiple Blast Walls" mode can be selected in + Expert mode. + +-Medium Floor is now set to use one height. Pack + button now changes floor width, for easy "padding" + of large areas. Height of Medium Floor can be changed + in Expert mode. + +-Added "Cubic Replace" mode to Force Field pack in + Expert mode. In this mode any cubic shape can be + replaced with a Force Field. + +-Added admin menu item to enable/disable Expert mode. + +-Added Expert Mode, which enables more pack options for + some deployables, usable with Repair Kit key. + +-Pieces will no longer cascade when destroyed in + Purebuild mode. + +-Added new Medium Floor and Light Walkway snap-to code, + developed by Mostlikely. + +-Deployed Large Station Inventories are now deleted + when they are destroyed. Normal Station Inventories + behave as normal. + +-Added telepads to savebuilding.cs. + +-Telepads no longer malfunction. They will always work, + until they are destroyed. + +-Rewrote Telepad pack. Should always work when there + is another telepad to teleport to. + +-Added admin menu item to enable/disable "Only Owner + Rotate mode", which will only let the creator of + an object rotate it. + +-Added admin menu item to enable/disable "Only Owner + Cascade mode", which will only let the creator of + an object cascade deconstruct it. + +-Added new Construction Tool, developed by Mostlikely. + This tool has 3 modes, each with several submodes: + * deconstruct + - normal + - cascading + * rotate + - pull + - push + * advanced Rotate + - select target as center of rotation + - select objects to rotate + - select rotation speed + - apply rotation + - display selection + - clear list + + Mine key selects main mode, grenade key selects + submode. + + Player can not select main mode or submode while carrying + mines or grenades. + +-Removed Deconstructor Gun. + +-Added entirely new rotation and deployment code, + developed by Mostlikely. + +-Inventory list rearranged to find deployables easier. + +**********************0.55 Alpha********************** + +-Force Field pack now detects other force fields when + finding size. + +-Rearranged and grouped admin and vote menu items. + +-Added admin menu item to enable/disable "Only Owner + Deconstruct mode", which will only let the creator of + an object deconstruct it. + +-Medium Floors now have 5 different height options: + 1.5 meter, 5 meter, 10 meter, 20 meter and 40 meter. + Default is 20 meter. + +-Only player-deployed Station Inventories can now be + deconstructed. + +**********************0.54 Alpha********************** + +-If Satchel charges are disabled, they can no longer be + detonated, even if thrown before they were disabled. + +-Super Admins can now give admin rights to players, even + if $Host::allowAdminPlayerVotes is enabled. + +-Jump Pad now only boosts once. + +-Added new forcefields to savebuilding.cs. + +-Made force field pads slightly larger than the normal + pad size. This will stop flickering where they border + with other deployables, like Light Support Beams. + +-Made it impossible to deploy inside or through a + force field. + +-Added new Force Field pack with deconstructible force + field pad. + + Force Field pack has 21 modes: + 3 groups: solid, team-pass, all-pass. + 7 colours in each group: white, red, green, blue, + cyan, magenta, yellow. + + Number in mode change message shows number of changes + required to reach next group. Example: + "(4) Force field set to solid blue" means 4 mode changes + are needed to reach team-pass group. + +-Shocklance weapon reverted to base functionality. + +-Fixed the way deploying of Light Support Beam pads + inside fames greater than max pad width is handled. + +-A big cleanup in deployables code. + +-Thrown items 'melt' time changed from 30 to 60 seconds. + +-Packs left from deconstructed items will now 'melt' if + left for too long, just like normal thrown items. + +-Added cams for team 0 (observer), 1 and 2 to let players + observe inmates through Commander Hud. + +-Replaced a missing function in prison.cs. Oops! + +**********************0.53 Alpha********************** + +-Put in an extra safery check to prevent objects from + disappearing randomly. This /should/ have been handled + by the game engine. + +-Fixed problem with Light Support Beams sometimes + deploying at extremely weird angles when deployed + on other funky Light Support Beams. + +-Increased accuracy in some rotations by 2 decimal + spaces. Should fix those annoying inaccuracies when + working on larger projects. + +-Plasma and Chaingun reverted to base values. + +**********************0.52 Alpha********************** + +-Fixed Medium Floor rotations being off by 90 deg when + deploying on another Medium Floor. + +-Max size of Light Support Beam pads changed to + 160 x 160 meters. + +-Touched up prison.cs. New host prefs options. Fixed + lighting issue. + +-Changed wording associated with the enabling/disabling + vehicles admin menu to be more clearly understandable. + +-All turret barrels reverted to normal. They will no + longer blow you and/or your building away from halfway + across the mission. ;) + +-Added admin menu item to enable/disable nerf weapons. + +-Pure armor now has same physical properties as Light, + except energy drain, recharge rate, jet force and + impact damage velocity. + +-Reverted all armors to base values. + +-Energizers no longer detonate on contact in Purebuild + mode. + +-Items do no longer animate on deconstruction. This should + fix nearly all the lag issues with cascading deconstruction. + +-Medium Floors changed from 8 x 8 to 8.5 x 8.5 meters + to fit "circle-deployed" 8 meter Light Support Beams. + +-Construction Mod deployables now use bottomPrint to + show pack mode changes. + +**********************0.51 Alpha********************** + +-Jumpads can now be deconstructed. + +-Jumpads are now static shapes, not items. + Note, if you have any saved structures with jump pads + in them, you must replace all instances of + "new Item()" with "new StaticShape()" in the save file. + +-Nerf guns are now available in Purebuild mode. + +-Loaded Medium Support Beams now no longer take down all + the deployables in the mission when they are destroyed. + +**********************0.50 Alpha********************** + +-New maintainer; JackTL. + +-Tightened up "security" in Purebuild mode. Only Pure + armor available in Purebuild mode, unless you're admin + or super admin. Pure armor can not use satchel charges. + Pure armor is still available in non-Purebuild mode, + though. + +-Pure armors can pilot vehicles. + +-Added admin menu item to pure/unpure vehicles. + +-Added admin menu item to toggle Invincible Armors. + +-Satchel Charge now tells everyone who dropped it. + +-Added Satchel Charge enable/disable control to admin menu. + +-Restored Team Damage vote and admin menu, added a separate + Purebuild menu item. + +-Disabling Purebuild no longer clears all deployables + in a mission. A new admin menu item replaces this + functionality. + +-Purebuild mode is now saved and loaded with server prefs. + +-Added save building script. Hosts only. Only usable + from console, for now. See scripts/savebuilding.cs for + details and help. + +-Medium Floors restored. New texture. + +-Light Blast Walls are stronger. + +-Added 1.5 and 4 meter beams to Light Support Beam pack. + +-New shape for Light Support Beam pack (so far). Watch those + busy fireflies buzz about! ;) + +-Tweaked armor impact damage values back to base levels. + +-Tweaked player sensors to have a huuuge radius, + and ignore LOS. Handy for people with waypoint scripts. + I may remove this if it causes lag. Shouldn't be a problem + with the small number of players usually in a single + Construction server. + +-Added nerf guns, with optional dance/death anims and + optional jail mode. 'Paintball' games! + +-Added nerf gun options to admin menu. + +-Added Super Chaingun, for demolition work. Only available + to admins. Automatically given at use of inventory station. + It may cause a bit of lag on large structures; use in bursts. + +-Plascannon now does double damage in blast radius. Added direct- + hit damage similar to mortar blast. Easier removal of spam, + without the randomness of the mortar. + +-Chaingun now does x4 damage, and has a tighter spread cone. + Easier pin-point removal of spammy items, especially mid-air + pieces. + + Note that the above weapon changes may go away if enough people + complain. If you host your own server, you can remove the changes + by deleting "plasma.cs" and "chaingun.cs" from your + "Construction\scripts\weapons" folder. + +-Added prison feature, for auto-punishing TK's and deployables + spammers, and to let admins deal with troublemakers without + kicking them. Handy for damage control when a n00b joins the game, + and you want him/her somewhere safe and not blowing up stuff while + you explain the point of the mod. + + Currently, non-auto prison is only available through console: + jailPlayer(clientId,release[1/0],time); + + Settings are saved with "prefs/ServerPrefs.cs" - no need to change + "prison.cs". + +-Added prison option to admin menu. + Note that if prison is added mid-mission, it will not be + lit (no lighting). + +-Admins can rain down a hail of fire on naughty players. + This can be very laggy if buildings are involved. Only + available through console (must be host), for now. + Type "JTLMeteorStrike();" in console for help, or see the + script file. + +-Added female and bioderm pure armors. + +-Increased Repair Gun range to 250 meters. + +-Fixed some typos. + +-Made other small changes. + +**********************0.48 Alpha********************** + +-Added the purebuild feature. + +***Construct*** + +-Included my spiffy DSO remover DOS batch file. + +-Fixed the deconstructor chat hud spam? (I thought I did) + +-Added the banana peel Glockenspeil. + +**********************0.47 Alpha********************** + +-Added deployable large inv stations + +-Added an non cascading deoncstruction patch under protest. + If this is in the full version of the mod then contact me. + +-Improved deploying on things + +-Fixed the num-deployed resest bug. + +**********************0.46 Alpha********************** + +-Improved deploying by alot. + +-Gave deployables to correct armor sizes. + +-Added Deconstruction gun. + +-Added Load screen. + +-Added remote vehicle controlling + +-Added Medium Floor. + +-Fixed Energizer. + +-Fixed the Jumpad. + +-Improved the telleporter. + +-Removed useless parts (until futher notice) + +**********************\/ Pre-Alpha versions \/********************** + +-Added Deployable base turret. + +-Added Forcefields. + +-Added Telleport. + +-Added Medium Spine. + +-Fixed the blastwall. + +-Some more I can't remember. + +**********************Mostlikely********************************* + +-Remove BlastWall (until futher notice) + +-Added Upward collapsing + +-Added Destruction Debriss + +-Added Deconstruction Gun + +-Added spine swithing + +-Added credits list + +-Added versionhistory list + +-Added Todo-list + +-Added 90degrees walkways + +-Changed some vehicle stats [Construct] + +-Improved deploy flexibility (won't be buggy) + +-Improved downwards sloping walkways + +-Fixed the jump pad. (isn't needed since you have infi jet, so just don't use these indoors ;D ) + +-Fixed the (beacon) switching to match your pack. + +**********************Construct******************************** + +-Fixed inventory hud lower case words for "bunker", "walkway". + +-Repairpack works again and with a 15m increase in range for now(testing). + +-Jump pack deployed image changed to "nexusbase.dts". + +-Increased deployable walls, and beams to 700 (I ran out with just me making something). + +-Jetpack particles enhanced. + +-Marked some random scripts with !!!!STOP LOOK AT ME!!! [mostlikely] + ++I think that is all. + + +************************Mostlikely***************************** + +-Added Walk ways + +-Added walk ways sloping feature with beacon switching. + + + +************************Before that**************************** + +Uhhhmm... dunno... if you'r looking for anything... just read the readme.txt \ No newline at end of file diff --git a/readme.txt b/readme.txt new file mode 100644 index 0000000..7806311 --- /dev/null +++ b/readme.txt @@ -0,0 +1,86 @@ +Note: This readme.txt has not been updated recently. Please see Version-history.txt for latest changes. + +---- + +The BASIC IDEA: + +------------------------------------------------------------------------------------------- +We just like to build stuff. +------------------------------------------------------------------------------------------- +Up to now mods like ninja mod and warped where used to create the wierdest of structures. +However these mods being combat orientated where limited in their building flexiblity. +Therefor the man with the vision started "the construction mod" (or is it the mod named "construction"?) +Anyway this mod will feature tools to make building easier, better, more realistic, more balanced and all that what other modders promise. +It might someday very well feature gameplay that suits builders as well as non-builders. +However until that day this mod remains for the one intrested in building and only building. +But hey, there's a builder in everyone. +-------------------------------------------------------------------------------------------- + +*******************Features****************** + +[[Beacon switching]] +-Some packs have more than one function. +-use the beacon key to switch. + +[[Border snapping]] +-When deploying on the far edge of an object the object will snap correctly to the border. + +****************Current deployables*********** + +[[Light support beam]]<> +-Comes in 5 basic lengths 1.5 meter, 4 meter, 8 meter, 40 meter and 160 meter. +-Has two smart functions + +auto-size, will scales the beam between 0.5 and 16 meter, if not confined it will scale to 4 meters. + +Pad, Sizes like the auto-size beam, but also streches to create a platform. + +[[Light Blast Wall]]<> +-Works like the padsetting of the light support beam. +-User can specify if he's in or out side his building for deploy adjustments +-Light Blast walls can now create an good defence for buildings. + +Problems: Placing stuff on them doesn't not work 100% + +[[Light Walk Way]]<> +-Just face the edge of a cliff and deploy to create handy walkways. +-Can be set to slope 0%, 20%, 45% and 90% up and down. +-Use the beacons to switch modes. + +[[Medium support Beam]]<> +-Much stronger than it's light counter part. +-Doesn't adjust in lenght. +-Comes with rings you can deploy on, and stand on to easaly deploy another medium spine ontop. +-The rings can be removed sperately. + +[[Medium Floor]]<> +-Deploy these for a good start. +-Deploy floors on floors to create an adjectand floor at the closest edge your deploying on. + +[[Jumpad]]<> +-Launch the player up some distance. + +[[Telleporter]]<> +-40 different telle port frequencies. +-Will only telle port to the frequency it's set to. +-Both teams use the same 40 frequencies. +-Dangerous side effects that become worse when the telleport is damaged. + +[[Energizers]]<> +-Will replenish the energy of any player within its range. +-Using a higly unstable reactor. +-Don't touch these, and protect them from damage at all cost. + +[[Disk turret]]<> +-Usefull for protection +-Be carefull, if they hit your base, it will take damage. + +[[Deployable base turret]]<> +-Deploy these for extra protection. + +[[Deployable tree]]<> +-Make places look nicer with these things. + +Problems: Deploying on them will be screwed up. + +[[Deconsruct Gun]]<> +-If you make an mistake you can correct it with this with out any dangerous side effects. +-Make sure you remove mistakes right after you made them. \ No newline at end of file diff --git a/scripts/ConstructionGame.cs b/scripts/ConstructionGame.cs new file mode 100644 index 0000000..b512283 --- /dev/null +++ b/scripts/ConstructionGame.cs @@ -0,0 +1,100 @@ +// DisplayName = Construction + +//--- GAME RULES BEGIN --- +// Build +//--- GAME RULES END --- + +// spam fix +function ConstructionGame::AIInit(%game) { + //call the default AIInit() function + AIInit(); +} + +function ConstructionGame::allowsProtectedStatics(%game) { + return true; +} + +function ConstructionGame::clientMissionDropReady(%game, %client) { + messageClient(%client, 'MsgClientReady',"", %game.class); + messageClient(%client, 'MsgMissionDropInfo', '\c0You are in mission %1 (%2).', $MissionDisplayName, $MissionTypeDisplayName, $ServerName ); + DefaultGame::clientMissionDropReady(%game, %client); +} + +function ConstructionGame::onAIRespawn(%game, %client) +{ + //add the default task + if (! %client.defaultTasksAdded) + { + %client.defaultTasksAdded = true; + %client.addTask(AIPickupItemTask); + %client.addTask(AIUseInventoryTask); + %client.addTask(AITauntCorpseTask); + %client.addTask(AIEngageTurretTask); + %client.addTask(AIDetectMineTask); + %client.addTask(AIBountyPatrolTask); + %client.bountyTask = %client.addTask(AIBountyEngageTask); + } + + //set the inv flag + %client.spawnUseInv = true; +} + +function ConstructionGame::updateKillScores(%game, %clVictim, %clKiller, %damageType, %implement) { + if (%game.testKill(%clVictim, %clKiller)) { //verify victim was an enemy + %game.awardScoreKill(%clKiller); + %game.awardScoreDeath(%clVictim); + } + else if (%game.testSuicide(%clVictim, %clKiller, %damageType)) //otherwise test for suicide + %game.awardScoreSuicide(%clVictim); +} + +function ConstructionGame::timeLimitReached(%game) { + logEcho("game over (timelimit)"); + %game.gameOver(); + cycleMissions(); +} + +function ConstructionGame::scoreLimitReached(%game) { + logEcho("game over (scorelimit)"); + %game.gameOver(); + cycleMissions(); +} + +function ConstructionGame::gameOver(%game) { + //call the default + DefaultGame::gameOver(%game); + + //send the winner message + %winner = ""; + if ($teamScore[1] > $teamScore[2]) + %winner = %game.getTeamName(1); + else if ($teamScore[2] > $teamScore[1]) + %winner = %game.getTeamName(2); + + if (%winner $= 'Storm') + messageAll('MsgGameOver', "Match has ended.~wvoice/announcer/ann.stowins.wav" ); + else if (%winner $= 'Inferno') + messageAll('MsgGameOver', "Match has ended.~wvoice/announcer/ann.infwins.wav" ); + else if (%winner $= 'Starwolf') + messageAll('MsgGameOver', "Match has ended.~wvoice/announcer/ann.swwin.wav" ); + else if (%winner $= 'Blood Eagle') + messageAll('MsgGameOver', "Match has ended.~wvoice/announcer/ann.bewin.wav" ); + else if (%winner $= 'Diamond Sword') + messageAll('MsgGameOver', "Match has ended.~wvoice/announcer/ann.dswin.wav" ); + else if (%winner $= 'Phoenix') + messageAll('MsgGameOver', "Match has ended.~wvoice/announcer/ann.pxwin.wav" ); + else + messageAll('MsgGameOver', "Match has ended.~wvoice/announcer/ann.gameover.wav" ); + + messageAll('MsgClearObjHud', ""); + for(%i = 0; %i < ClientGroup.getCount(); %i ++) { + %client = ClientGroup.getObject(%i); + %game.resetScore(%client); + } + for(%j = 1; %j <= %game.numTeams; %j++) + $TeamScore[%j] = 0; +} + +function ConstructionGame::vehicleDestroyed(%game, %vehicle, %destroyer) { +} + diff --git a/scripts/Function Library R3.txt b/scripts/Function Library R3.txt new file mode 100644 index 0000000..7eaa542 --- /dev/null +++ b/scripts/Function Library R3.txt @@ -0,0 +1,275 @@ +Function.cs documantation - v3.5 +Created by DynaBlade +================================== +I dont mind if you use my scripts, as long as you say that +you are using them somewhere in the credits, say a webpage or a startup screen. +IF YOU DO NOT KNOW HOW TO USE THIS FUNCTION LIBRARY DO NOT ASK ME! This is +provided as a library reference only! +All functions used here are made strictly by DynaBlade. +Functions made in the other attached files are made by their respective authors. + + +TypeMasks +--------- +$AllObjMask +Every object in T2 falls under this category. Use this in your raycasts and +containerBox searches if you just want to find anything + +$DefaultLOSMask +Basic mask, usually used with raycasting LOS + +$CoreObjectMask +Players, Vehicles, Stations, Generators and Sensors fall in this category + +$EverythingObjectMask (not done) +This includes everything, even projectiles and possibly GUI objects! + +ShapeBase Commands +------------------ +These commands work on any object derived from ShapeBase. + +%obj.getRotation() +Gets the rotation of the object + +%obj.setRotation(%rot) +Sets the object's rotation of to %rot + +%obj.setPosition(%pos) +Sets the object's position to %pos + +%obj.getSlotRotation() +Gets the rotation of a specific slot on an object + +%obj.getSlotPosition() +Gets the position of a specific slot on an object + +%obj.zapObject() +Plays Shocklance "zap" animation on object + +%obj.zap2Object() +Plays a different "zap" animation on object + +%obj.stopZap() +Stops the Shocklance "zap" animation prematurely +(if you dont want it to fade out naturally) + +%obj.isPlayer() +Checks to see if object is a Player Object + +%obj.isVehicle() +Checks to see if object is a Vehicle Object + +%obj.applyKick(%force) +Applys a kick based on the force inputted based on the muzzle vector. +If there is no muzzle, then it apply an impulse at "0 0 0" at the shape's +current forward position + +%obj.useEnergy(%amount) +Uses %amount much energy assuming the shape has any + +%obj.play3D(sound) +Plays sound from the object + +%obj.teleportStartFX() +Teleportation fadeout used in Meltdown2 + +%obj.teleportEndFX() +Teleportation fadein used in Meltdown2 + +%obj.getEyePoint() +Usually used with Players, this gets the camera's current position + +%obj.getForwardRaycastPt(%dist) +Similar to MuzzleRaycast, but this one gets the raycast in whatever your +forward direction is + +%obj.getEyeRaycastPt(%dist) +Gets the camera's raycast from the scanning distance + +%obj.getMuzzleRaycastPt(%slot, %dist) +Gets the muzzle's raycast from the object usind the slot and scanning distance + +%obj.getMass() +Returns the mass of the object + +%obj.getAccel() +Returns the acceleration of the object in 1 millisecond. If you want to get an +acceleration of say, 1 second, you would scale the output vector by the number +of miliseconds you want it to be, in this case, 1 second = 1000 milliseconds. So, + +%accel_1_second = vectorScale(%obj.getAccel(), 1000); + +%obj.getVelToForce() +This converts the object's velocity to a force vector. This works sort of like a +setVelocity for vehicles, in that it outputs the vector ready to be applied to the object. +If you know what you're doing + +%obj.getMaxEnergy() +Returns the datablock maximum energy the object has, if any + +%obj.getMaxDamage() +Returns the datablock maximum damage the object has, if any + +%obj.getDamageLeft() +Returns the object's health, or damage away from the maximum, if any + +%obj.getDamageLeftPct() +Returns the percentage of non-damage on the object + +%obj.getDamagePct() +Returns the percentage of damage on the object + +%obj.getEnergyPct() +Returns the percentage of energy on the object + +%obj.getTransformAngle(%trans) +Returns the transform's angle + +** EXPERIMENTAL FUNCTIONS ** + +%obj.createSlotExtension(%obj, %slot) +Creates 8 more mountable slots at the cost of 1 +However, strange side effects seem to take place... You'd have to try this one out to see + +%obj.deleteSlotExtension(%obj, %slot); +Deletes the current slot extension. + +isWithinVariance(%va, %vb, %variance) +Tests vectors a and be to see if they are pointing within %variance direction +I'm not sure if I have the math skill to figure this one out. So I copied something +from inside T2's stuff that worked kinda like this. + +Normal Commands +--------------- + +combineVars(%a, %b, %c) +Combines 3 variables together into 1 variable (ex. Position) + +killit(%k) +same as %obj.delete() + +scanArea(%pos, %radius, %mask) +scans for existance of %mask type objects in a %radius area starting from %pos position + +testPosition(%pos) +Tests to see if you can move to this position + +createEmitter(%pos, %emitter, [%rot]) +Creates a particle emitter at %pos position and with particle emitter %emitter (rot is optional) + +createLifeEmitter(%pos, %emitter, %lifeMS, [%rot]) +This creates an emitter for %lifeMS time, if you dont want to have to worry +about deleting the particle emitter + +sqr(num) +returns number*number + +cube(num) +returns number*number*number + +modifyTransform(%trans1, %trans2) +This modifys transform1 based on transform2 +For example: modifyTransform("255 100 96 1 0 0 1.57", "-255 0 4 -1 1 0 0"); +would output the transform "0 100 100 0 1 0 1.57" + +modifyTri(%trans1, %trans2) +same as modifyTransform with 3 variables + +modifyQuad(%trans1, %trans2) +same as modifyTransform with 4 variables + +shutdownServer(%time, %msg, %lines) +Centerprints the text for %time amount of time and on %lines number of lines before +the server shuts down + +velToSingle(%vel) +Converts a 3-unit velocity vector to a single number constant + +msToKPH(%vel, true|false) +Converts a single number constant (velToSingle) to KPH, and if bool = true, it will +not round off calculations. + +KPHToMPH(%vel, true|false) +Converts a single number constant (velToSingle)from KPH to MPH, and if bool = true, it will +not round off calculations. + +vectorNeg(%vec) +Returns the negative of the inputted vector + +vectorClear(%vec) +Yes.... people may actually find this useful.. lol + +vectorCopy(%vec) +Returns this vector (dont even ask why) + +vectorCompare(%veca, %vecb) +Returns 1 if the vectors are the same or similar + +vectorToRotZ(%vec) +Converts a vector to a Z rotation. Hey! I'm not that smart yet + +getLOSOffset(%obj, %vec, %dist) +Returns a position from a vector and a distance. + +getVectorFromPoints(%a, %b) +Returns the Normalized vector for pointa facing pointb + +getVectorFromObjects(%a, %b) +Same as above, but with objects + +getDistance2D(%a, %b) +Returns the distance between the 2 2-unit vectors + +getDistance3D(%ptA, %ptB) +returns the distance between two positions + +getObjectDistance(%obj1, %obj2) +returns the distance between 2 objects + +setFlightCeiling(height) +Sets the mission's flight 'ceiling', or maximum distance +upwards before your engines/jets cut off + +reload(%script) +This functions like exec, only it causes lag because it is loading all +the datablocks in the file you called this with to all the connected +clients on the server, and to the server itself. This function, along +with plain ol' exec will allow you to literally build your mod while +others play it! + +changeServerHostName(%name) +Changes the name of server you are hosting, without need for reset. + +changeServerPlayerCount(%number) +Changes the # of players your server can accept, without need for reset. + +changeServerAllowAliases(true|false) +Changes the allow aliases switch while you are hosting, without need for reset. + +changeServerAdminPassword(%pass) +Changes the server admin password, without need for reset. + +changeServerPassword(%name) +Changes the entry password on server you are hosting, without need for reset. + +setServerPrefs(%name, %aliases, %admin, %password, %numplayers) +Changes all of the above, but with one function + +getRandomN([%max, %min]) +Gets a random negative number, min and max values optional. + +getRandomB() +Returns true or false, at random. + +getRandomT([%max, %min]) +Gets a positive OR negative random number at random will it be either +Max and min values can be defined + +vectorRandom() +Creates a vector pointing in any random 360* direction + +================================================================================== +Notes: +Particle emitter rptation should work now, and is optional. +Reload doesnt always load the full datablock, and I dont know why. +I am not good at math :( \ No newline at end of file diff --git a/scripts/JTLmeteorStorm.cs b/scripts/JTLmeteorStorm.cs new file mode 100644 index 0000000..6319aea --- /dev/null +++ b/scripts/JTLmeteorStorm.cs @@ -0,0 +1,196 @@ +// JTLmeteorStorm.cs +// +// This script (C) 2002 by JackTL +// +// Use, modify, but give credit +// +// Functions: +// +// JTLMeteorStorm(obj,forcePlayer[1/0],maxRad,numFb,dropAlt,dropAltVariance,dbName,dbType,timeOutMS,randomRot[1/0],randomPulse[1/0],maxPulse,speedVec,offsetSpeedVec[1/0]) +// + +datablock ParticleData(JTLMeteorStormFireballParticle) { + dragCoeffiecient = 0.0; + gravityCoefficient = -0.2; + inheritedVelFactor = 0.0; + + lifetimeMS = 350; + lifetimeVarianceMS = 0; + + textureName = "particleTest"; + + useInvAlpha = false; + spinRandomMin = -160.0; + spinRandomMax = 160.0; + + animateTexture = true; + framesPerSec = 15; + + animTexName[0] = "special/Explosion/exp_0016"; + animTexName[1] = "special/Explosion/exp_0018"; + animTexName[2] = "special/Explosion/exp_0020"; + animTexName[3] = "special/Explosion/exp_0022"; + animTexName[4] = "special/Explosion/exp_0024"; + animTexName[5] = "special/Explosion/exp_0026"; + animTexName[6] = "special/Explosion/exp_0028"; + animTexName[7] = "special/Explosion/exp_0030"; + animTexName[8] = "special/Explosion/exp_0032"; + + colors[0] = "1.0 0.7 0.5 1.0"; + colors[1] = "1.0 0.5 0.2 1.0"; + colors[2] = "1.0 0.25 0.1 0.0"; + sizes[0] = 3.0; + sizes[1] = 1.0; + sizes[2] = 0.5; + times[0] = 0.0; + times[1] = 0.2; + times[2] = 1.0; +}; + +datablock ParticleEmitterData(JTLMeteorStormFireballEmitter) { + ejectionPeriodMS = 5; + periodVarianceMS = 1; + + ejectionVelocity = 0.25; + velocityVariance = 0.0; + + thetaMin = 0.0; + thetaMax = 30.0; + + particles = "JTLMeteorStormFireballParticle"; +}; + +datablock GrenadeProjectileData(JTLMeteorStormFireball) { + projectileShapeName = "weapon_chaingun_ammocasing.dts"; + emitterDelay = -1; + directDamage = 0; + directDamageType = $DamageType::Meteor; + hasDamageRadius = false; // true; + indirectDamage = 0; // 0.5; + damageRadius = 7.5; + radiusDamageType = $DamageType::Meteor; + kickBackStrength = 1750; + explosion = PlasmaBoltExplosion; + splash = PlasmaSplash; + baseEmitter = JTLMeteorStormFireballEmitter; + armingDelayMS = 50; + grenadeElasticity = 0.15; + grenadeFriction = 0.4; + drag = 0.1; + gravityMod = 0.0; + sound = GrenadeProjectileSound; + + hasLight = true; + lightRadius = 20.0; + lightColor = "1 1 0.5"; +}; + +function JTLMeteorStormFireball::onExplode(%data,%proj,%pos,%mod) { + // Ass-ume gravity does not change vec.. (gravityMod = 0.0) :P + %vec = vectorNormalize(%proj.initialDirection); + if (%data.hasDamageRadius) + RadiusExplosion(%proj,vectorAdd(%pos,vectorScale(%vec,-0.1)),%data.damageRadius,%data.indirectDamage,%data.kickBackStrength,%proj.sourceObject,%data.radiusDamageType); + %pPos = %proj.getPosition(); + %surface = containerRayCast(vectorAdd(%pPos,vectorScale(%vec,-0.1)),vectorAdd(%pPos,vectorScale(%vec,1)),-1,%proj); + %tObj = firstWord(%surface); + if (isObject(%tObj)) + %tObj.damage(%proj,%pPos,0.4,%proj.getDataBlock().directDamageType); +// ionStormBeam(vectorAdd(%pPos,"0 0" SPC $IonStorm::Height)); +} + +function JTLMeteorStorm (%obj,%forcePlayer,%maxRad,%numFb,%dropAlt,%dropAltVariance,%dbName,%dbType,%timeOutMS,%randomRot,%randomPulse,%maxPulse,%speedVec,%offsetSpeedVec,%createFB,%pos,%target) { + %pi = 3.1415926535897932384626433832795; // Whoa.. + if (%createFB) { + if (%randomRot) + %rot = "0 0 1" SPC getRandom() * (%pi * 2); + else + %rot = "1 0 0 0"; + %fb = new (%dbType) (JTLMeteor) { + dataBlock = %dbName; + position = %pos; // Needed for non-projectile types + initialPosition = %pos; + initialDirection = %speedVec; +// sourceObject = 0; + sourceSlot = 0; + vehicleObject = 0; + }; + if (isObject(%target) && $JTLMeteorStormSeek == 1 && %dbType $= "SeekerProjectile") + %fb.setObjectTarget(%target); + %fb.setRotation(%rot); + if (%randomPulse) { + %pulse = getRandom() * %maxPulse; + %iPos = vectorNormalize((getRandom() * 2) - 1 SPC (getRandom() * 2) - 1 SPC (getRandom() * 2) - 1); + %iPos = vectorAdd(%pos,%iPos); + %iVec = vectorScale(vectorNormalize(getRandom() SPC getRandom() SPC getRandom()),%pulse); +// Fix this, not for projectiles + %fb.applyImpulse(%iPos,%iVec); + } + if (%dbType $= "Item") + %fb.setVelocity(%speedVec); // Needed for non-projectile types + MissionCleanup.add(%fb); + if (%timeOutMS) { + %fb.schedule(%timeOutMS,setDamageState,Destroyed); + %fb.schedule(%timeOutMS+1000,delete); + } + return; + } + + if (%forcePlayer) { + %obj = %obj.player; + } + else { + if (%obj.getClassName() $= "GameConnection" || %obj.getClassName() $= "AIConnection") { + %obj2 = %obj.getControlObject(); + if (isObject(%obj2)) + %obj = %obj2; + } + } + + if (isObject(%obj)) { + if (%maxRad < 1) + %maxRad = 50; + if (%numFb < 1) + %numFb = 100; + if (%dropAlt < 1) + %dropAlt = 100; + if (%dropAltVariance < 1) + %dropAltVariance = 500; + if (!isObject(%dbName)) + %dbName = "JTLMeteorStormFireball"; + if (%dbType $= "" || %dbType $= "0") + %dbType = "GrenadeProjectile"; + if (%speedVec $= "" || %speedVec $= "0") + %speedVec = "0 0 -2"; + if (%maxPulse < 1) + %maxPulse = 4000; + %p = %obj.getWorldBoxCenter(); + %x = getWord(%p,0); + %y = getWord(%p,1); + %z = getWord(%p,2); + for (%i = 0; %i < %numFb; %i++) { + %dVec = getRandom() * %pi * 2; + %dRad = getRandom() * %maxRad; + %dX =mSin(%dVec) * %dRad; + %dY =mCos(%dVec) * %dRad; + %dZ =%dropAlt + (getRandom() * %dropAltVariance); + if (%offsetSpeedVec) { + %v2 = vectorCross(vectorNormalize(%speedVec),"1 0 0"); + %v3 = vectorCross(vectorNormalize(%speedVec),%v2); + %dPos = vectorAdd(%p,vectorScale(vectorNormalize(%speedVec),-%dZ)); + %dPos = vectorAdd(%dPos,vectorScale(%v2,%dX)); + %dPos = vectorAdd(%dPos,vectorScale(%v3,%dY)); + } + else { + %dX = %x + %dX; + %dY = %y + %dY; + %dZ = %z + %dZ; + %dPos = %dX SPC %dY SPC %dZ; + } + JTLMeteorStorm(0,0,0,0,0,0,%dbName,%dbType,%timeOutMS,%randomRot,%randomPulse,%maxPulse,%speedVec,0,true,%dPos,%obj); + } + } + else { + error("-JTLMeteorStorm- no valid object."); + error("Usage: JTLMeteorStorm(obj,forcePlayer[1/0],maxRad,numFb,dropAlt,dropAltVariance,dbName,dbType,timeOutMS,randomRot[1/0],randomPulse[1/0],maxPulse,speedVec,offsetSpeedVec[1/0])"); + } +} diff --git a/scripts/MPM/MPM.cs b/scripts/MPM/MPM.cs new file mode 100644 index 0000000..a0250e0 --- /dev/null +++ b/scripts/MPM/MPM.cs @@ -0,0 +1,795 @@ + + + + +datablock ParticleData(MpmFlareParticle1) +{ + dragCoeffiecient = 0.0; + gravityCoefficient = 0.0; + inheritedVelFactor = 1.0; + + lifetimeMS = 500; + lifetimeVarianceMS = 0; + + spinRandomMin = 0.0; + spinRandomMax = 0.0; + windcoefficient = 0; + textureName = "skins/jetflare03"; + + colors[0] = "0.7 0.7 1.0 0.5"; + colors[1] = "0.7 0.7 1.0 0.5"; + colors[2] = "0.7 0.7 1.0 0.5"; + colors[3] = "0.7 0.7 1.0 0.5"; + + sizes[0] = 50; + sizes[1] = 50; + sizes[2] = 50; + sizes[3] = 50; + + times[0] = 0.25; + times[1] = 0.25; + times[2] = 0.25; + times[3] = 1; + +}; + +datablock ParticleData(MpmFlareParticle3) +{ + dragCoeffiecient = 0.0; + gravityCoefficient = 0.0; + inheritedVelFactor = 1.0; + + lifetimeMS = 1000; + lifetimeVarianceMS = 0; + + spinRandomMin = 0.0; + spinRandomMax = 0.0; + windcoefficient = 0; + textureName = "skins/jetflare03"; + + colors[0] = "0.7 0.7 1.0 0.5"; + colors[1] = "0.7 0.7 1.0 0.5"; + colors[2] = "0.7 0.7 1.0 0.5"; + colors[3] = "0.7 0.7 1.0 0.5"; + + sizes[0] = 50; + sizes[1] = 50; + sizes[2] = 50; + sizes[3] = 50; + + times[0] = 0.0; + times[1] = 0.25; + times[2] = 0.5; + times[3] = 0.75; + +}; + +datablock ParticleData(MpmFlareParticle2):MpmFlareParticle1 +{ +textureName = "skins/jetpackflare_bio"; +useInvAlpha = 0; +lifetimeMS = 2500; +spinRandomMin = -360.0; +spinRandomMax = 360.0; +sizes[0] = 15; +sizes[1] = 15; +sizes[2] = 15; +sizes[3] = 15; +}; + +datablock ParticleData(MpmJetSmoke1) +{ + dragCoeffiecient = 0.0; + gravityCoefficient = 0.0; + inheritedVelFactor = 0.0; + + lifetimeMS = 60000; + lifetimeVarianceMS = 0; + + spinRandomMin = 0.0; + spinRandomMax = 0.0; + windcoefficient = 0.5; + textureName = "skins/jetflare2"; + + colors[0] = "0.8 0.8 0.8 1"; + colors[1] = "0.8 0.8 0 0.9"; + colors[2] = "0.8 0.8 0.8 0.5"; + colors[3] = "0.8 0.8 0.8 0.0"; + + sizes[0] = 5; + sizes[1] = 17; + sizes[2] = 18; + sizes[3] = 20; + + times[0] = 0; + times[1] = 0.25; + times[2] = 0.5; + times[3] = 0.75; + +}; + + + +datablock ParticleData(MpmJetSmoke2):MpmJetSmoke1 +{ + + dragCoeffiecient = 0.0; + gravityCoefficient = 0.0; + inheritedVelFactor = 0.0; + + lifetimeMS = 60000; + lifetimeVarianceMS = 0; + + spinRandomMin = 0.0; + spinRandomMax = 0.0; + windcoefficient = 0.5; + textureName = "skins/jetflare2"; + + colors[0] = "0.8 0.8 0.8 1"; + colors[1] = "0.8 0.8 0 0.9"; + colors[2] = "0.8 0.8 0.8 0.5"; + colors[3] = "0.8 0.8 0.8 0.0"; + + sizes[0] = 5; + sizes[1] = 17; + sizes[2] = 18; + sizes[3] = 20; + + times[0] = 0; + times[1] = 0.25; + times[2] = 0.5; + times[3] = 0.75; + + + +}; + + + +datablock ParticleEmitterData(MpmFlareEmitter1) +{ + lifetimeMS = 10; + ejectionPeriodMS = 100; + periodVarianceMS = 0; + + ejectionVelocity = 0.1; + velocityVariance = 0.0; + ejectionoffset = 5; + thetaMin = 0.0; + thetaMax = 0.0; + + + orientParticles = false; + orientOnVelocity = false; + + particles = "MpmFlareParticle1"; +}; + +datablock ParticleEmitterData(MpmFlareEmitter2):MpmFlareEmitter1 +{ +particles = "MpmFlareParticle2"; +}; + +datablock ParticleEmitterData(MpmJetEmitter1) +{ + lifetimeMS = 10; + ejectionPeriodMS = 10; + periodVarianceMS = 0; + + ejectionVelocity = 10.0; + velocityVariance = 1.0; + ejectionoffset = 0; + thetaMin = 0.0; + thetaMax = 5.0; + + + orientParticles = false; + orientOnVelocity = false; + + particles = "MpmJetSmoke1"; +}; + +datablock ParticleEmitterData(MpmJetEmitter2):MpmJetEmitter1 +{ + ejectionPeriodMS = 10; + particles = "MpmJetSmoke2"; + thetaMin = 0.0; + thetaMax = 1.5; +}; + + +datablock ParticleEmitterData(MpmJetEmitter3):MpmJetEmitter1 +{ + ejectionPeriodMS = 30; + ejectionVelocity = 4.0; + velocityVariance = 1.0; + particles = "MpmFlareParticle2"; + ejectionoffset = 10; + thetaMin = 0.0; + thetaMax = 360.0; + +}; + +datablock TracerProjectileData(Mpm_G_PR) { + className = "TracerProjectileData"; + emitterDelay = "-1"; + velInheritFactor = "0"; + directDamage = "0"; + hasDamageRadius = "0"; + indirectDamage = "0"; + damageRadius = "0"; + radiusDamageType = "0"; + kickBackStrength = "0"; + Explosion = "TurretExplosion"; + hasLight = "0"; + lightRadius = "1"; + lightColor = "1.000000 1.000000 1.000000 1.000000"; + hasLightUnderwaterColor = "0"; + underWaterLightColor = "1.000000 1.000000 1.000000 1.000000"; + explodeOnWaterImpact = "0"; + depthTolerance = "5"; + bubbleEmitTime = "0.5"; + faceViewer = "0"; + scale = "1 1 1"; + dryVelocity = "0.1"; + wetVelocity = "0.1"; + fizzleTimeMS = "32"; + lifetimeMS = "32"; + explodeOnDeath = "1"; + reflectOnWaterImpactAngle = "0"; + deflectionOnWaterImpact = "0"; + fizzleUnderwaterMS = "-1"; + activateDelayMS = "-1"; + doDynamicClientHits = "0"; + tracerLength = "1"; + tracerMinPixels = "1"; + tracerAlpha = "0"; + tracerColor = "0.000000 0.000000 0.000000 0.000000"; + tracerTex[0] = "special/tracer00"; + tracerTex[1] = "special/tracercross"; + tracerWidth = "0.1"; + crossViewAng = "0.99"; + crossSize = "0.1"; + renderCross = "0"; + isFXUnit = "1"; +}; + + + +datablock SeekerProjectileData(MpmMissile1) +{ + heatSignature = 1; + sensorData = DeployedOutdoorTurretSensor; + casingShapeName = "weapon_missile_casement.dts"; + projectileShapeName = "bomb.dts"; + hasDamageRadius = false; + indirectDamage = 0; + damageRadius = 0; + radiusDamageType = $DamageType::Missile; + kickBackStrength = 20000; + + explosion = "GrenadeExplosion"; + 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 = MpmJetEmitter1; + delayEmitter = MpmFlareEmitter1; + puffEmitter = MissilePuffEmitter; + bubbleEmitter = GrenadeBubbleEmitter; + bubbleEmitTime = 1.0; + + exhaustEmitter = MissileLauncherExhaustEmitter; + exhaustTimeMs = 300; + exhaustNodeName = "muzzlePoint1"; + + lifetimeMS = -1; + muzzleVelocity = 0.1; + maxVelocity = 8000; + turningSpeed = 0.0; + acceleration = 1; + scale = "1 1 1"; + proximityRadius = 3; + + terrainAvoidanceSpeed = 180; + terrainScanAhead = 25; + terrainHeightFail = 12; + terrainAvoidanceRadius = 100; + + flareDistance = 0; + flareAngle = 0; + + sound = HAPCFlyerThrustSound; + //BomberFlyerThrustSound; + explodeOnDeath = "1"; + hasLight = true; + lightRadius = 10.0; + lightColor = "1 1 0"; + + useFlechette = false; + flechetteDelayMs = 550; + casingDeb = FlechetteDebris; + + explodeOnWaterImpact = true; +}; + + + +datablock GrenadeProjectileData(BoosterGrenade) +{ + projectileShapeName = "grenade_projectile.dts"; + emitterDelay = -1; + directDamage = 0.0; + hasDamageRadius = true; + indirectDamage = 0.1; + damageRadius = 0.1; + radiusDamageType = $DamageType::Grenade; + kickBackStrength = 1500; + bubbleEmitTime = 1.0; + + sound = GrenadeProjectileSound; + explosion = "GrenadeExplosion"; + underwaterExplosion = "UnderwaterGrenadeExplosion"; + velInheritFactor = 0.5; + splash = GrenadeSplash; + + //baseEmitter = //MpmJetEmitter2; + bubbleEmitter = GrenadeBubbleEmitter; + + grenadeElasticity = 0.35; + grenadeFriction = 0.2; + armingDelayMS = 250; + muzzleVelocity = 10; + drag = 0.1; +}; + + +datablock SeekerProjectileData(MpmMissile2):MpmMissile1 +{ + directDamage = 0.0; + hasDamageRadius = true; + indirectDamage = 0.1; + damageRadius = 0.1; + +explosion = LargeAirVehicleExplosion; + explosionDamage = 0.5; + explosionRadius = 0.2; + +muzzleVelocity = 0.1; +maxVelocity = 80000; +acceleration = 1; + +projectileShapeName = "weapon_missile_casement.dts"; +baseEmitter = MpmJetEmitter2; +delayEmitter = MpmFlareEmitter2; +lifetimeMS = -1; + sound = HAPCFlyerThrustSound; +}; + +datablock SeekerProjectileData(MpmMissile3):MpmMissile2 +{ +lifetimeMS = -1; +muzzleVelocity = 20; //5 +maxVelocity = 20;//80 +acceleration = 0; //1 +}; + +function MpmMissile1::onExplode(%data, %proj, %pos, %mod) +{ +%proj.load.Explode(%proj,%pos); +//parent::onExplode(%data,%proj,%pos,%mod); +} + +function Mpm_B_MIS::onExplode(%data, %proj, %pos, %mod) +{ +%proj.load.Explode(%proj,%pos); +//parent::onExplode(%data,%proj,%pos,%mod); +} + +function Mpm_B_MIS1::onExplode(%data, %proj, %pos, %mod) +{ +%proj.load.Explode(%proj,%pos); +//parent::onExplode(%data,%proj,%pos,%mod); +} + +function Mpm_B_MIS2::onExplode(%data, %proj, %pos, %mod) +{ +//Anti missile missile :D +//%proj.load.Explode(%proj,%pos); +//parent::onExplode(%data,%proj,%pos,%mod); +} + +function Mpm_B_MIS3::onExplode(%data, %proj, %pos, %mod) +{ +%proj.load.Explode(%proj,%pos); +//parent::onExplode(%data,%proj,%pos,%mod); +} + +function Mpm_B_MIS4::onExplode(%data, %proj, %pos, %mod) +{ +%proj.load.Explode(%proj,%pos); +//parent::onExplode(%data,%proj,%pos,%mod); +} + + +function MpmMissile1::onCollision(%data, %projectile, %targetObject, %modifier, %position, %normal) +{ +parent::onExplode(%data,%projectile,%position,%modifier); +} + + +function MpmMissile2::onExplode(%data, %proj, %pos, %mod) +{ + +%speed = GetWords(%proj.predict(),3,5); +%dir = VectorScale(%speed,1/BasicGrenade.muzzlevelocity); +%p1 = new GrenadeProjectile() + { + dataBlock = BoosterGrenade; + initialDirection = %dir; + initialPosition = %pos; + }; +%proj.delete(); +} + +function MpmMissile3::onExplode(%data, %proj, %pos, %mod) +{ +%speed = GetWords(%proj.predict(),3,5); +%dir = VectorScale(%speed,1/BasicGrenade.muzzlevelocity); +%p1 = new GrenadeProjectile() + { + dataBlock = BoosterGrenade; + initialDirection = %dir; + initialPosition = %pos; + }; +%proj.delete(); +} + +function SeekerProjectile::Predict(%p,%ttime) +{ +%time = ((GetSimTime()+%ttime) - %p.createtime)/1000; +%dat = %p.getDatablock(); +%startspeed = VectorScale(%p.InitialDirection,%dat.muzzleVelocity); +if (%p.sourceObject) + { + %co1 = mAbs(VectorDot(%p.InitialDirection,VectorNormalize(%p.startVelocity))); + %sourceSpeed = VectorScale(%p.startVelocity,%dat.velInheritFactor*%co1); + //if (%p.speedmod == 1) + %sourceSpeed = VectorAdd(%sourcespeed,VectorScale(VectorNormalize(%p.startVelocity),-0.5)); + %leng = mAbs(VectorDot(%p.InitialDirection,%p.startVelocity)); + %dir = VectorNormalize(%p.initialdirection); + %sourceSpeedlen = VectorDot(%SourceSpeed,VectorNormalize(%p.initialDirection)); + } +%speedaccel = Limit(%dat.acceleration*(%time-1),0,Limit(%dat.maxVelocity-(%dat.muzzleVelocity+%sourceSpeedlen),0)); +%accelVec = VectorScale(vectorNormalize(%p.InitialDirection),%speedaccel); + +%Speed = VectorAdd(VectorAdd(%startspeed,%sourceSpeed),VectorAdd(%accelvec,%gravvec)); + +%distance1 = VectorScale(%startspeed,%time); +%distance2 = VectorScale(%sourceSpeed,%time); + +%distance3 = VectorScale(%accelvec,0.5*(%time)); +%distance = VectorAdd(VectorAdd(%p.initialPosition,%distance3),VectorAdd(%distance2,%distance1)); + +//if (!%p.speedmod) + //%p.speedmod = 1; + +//if (VectorDist(%distance,%p.getTransform())>4) + //%p.speedmod *= -1; + +if (getSimTime()-%p.lasttime>1000) + %p.schedule(%ttime,"logerror",%distance); +%distance=VectorAdd(%distance,VectorScale(%p.lasterror,-1)); + +return %distance SPC %speed; +} + +function testpred(%dir,%speed,%time) +{ +%p = Launch_Mpm("0 0 110",%dir,%speed,%time*1000,mpmMissile1); +for (%t=0;%t < %time;%t++) + { + %p.schedule(%t*1000,predict); + } +} + + + +function putwp(%pos) +{ + +%wp = new WayPoint() { + position = %pos; + rotation = "1 0 0 0"; + scale = "1 1 1"; + dataBlock = "WayPointMarker"; + team = 1; + }; +%wp.schedule(5000,"delete"); +} + + +function SeekerProjectile::logerror(%p,%distance) +{ +%p.lasterror = VectorSub(%distance,%p.getTransform()); +%p.lasttime = (GetSimTime()-%p.createtime)/1000; +} + + +function ItemData::Stage1(%data,%p) +{ + +if (IsObject(%p)) + { + } +} + +function ItemData::Stage2(%data,%p) +{ + +if (IsObject(%p)) + { + %start = GetWords(%p.traject,0,2); + %up = GetWords(%p.traject,3,5); + %loc = GetWord(%p.traject,6); + %a = GetWord(%p.traject,7); + %vector = GetWords(%p.traject,8,10); + %time = GetWord(%p.traject,11); + %stlevel = %p.getTransform();//VectorAdd(%start,VectorScale(%up,%loc)); + %stspeed = VectorScale(%up,%a); + %missileblock = %p.load.missile; + %p2 = Launch_Mpm(%stlevel,%vector,%stspeed,%time+50000,%missileblock); + %p2.team = %p.team; + %p2.source = %p.source; + %p2.traject = %p.traject; + %p2.load = %p.load; + %p2.owner = %p.owner; + %p2.s2time = %time; + %p2.targetlocation = %p.targetlocation; + %p2.stage2 = %p2.load.schedule(%time,"AtTarget",%p2); + if (%p.owner.getControlObject() == %p.owner.comcam && %p.owner.moveprojectile = %p) + obsproj(%p2,%p.owner); + return %p2; + } +} + +datablock ItemData(Mpm_Null_Load) +{ + cost = 0; + missile = Mpm_B_MIS1; + name = "Null"; + friendly = 0; +}; + +function testenemy(%pos,%dir,%speed,%time) +{ +%p = Launch_Mpm(%pos,%dir,%speed,%time,MpmMissile1); +%p.team = 0; +%p.load = Mpm_Null_Load; +%p.schedule(360000,"delete"); +} + +function ItemData::AtTarget(%data,%p) +{ + +if (IsObject(%p)) + { + //do nothing + } +} + +function ItemData::Explode(%data,%p,%pos) +{ + +if (IsObject(%p)) + { + if (IsObject(%data.vehicle)) + //if(VectorDist(%p.targetlocation,%pos)<50) + Mpm_VE_Load0.AtTarget(%p); + } +} + +function Mpm_Nuke_Load::Explode(%data,%p,%pos) +{ +if (IsObject(%p)) + { + BigFatNukeTarget(%pos); + } +} + +function Mpm_Nuke2_Load::Explode(%data,%p,%pos) +{ +if (IsObject(%p)) + { + ShoulderNuclear.onExplode(%p, %pos); + } +} + + + +function Mpm_Hole_Load::Explode(%data,%p,%pos) +{ +if (IsObject(%p)) + { + %mask = $TypeMasks::StaticShapeObjectType | $TypeMasks::ForceFieldObjectType | $TypeMasks::InteriorObjectType; + %res = containerRayCast(%pos,"0 0 500",%mask, %p); + if (%res) + %inside = 1; + dome(VectorAdd(%pos,"0 0" SPC (1-%inside)*200),60000,%inside); + } +} + + +function ItemData::InterCept(%data,%p) +{ +if (IsObject(%p)) + { + //Be suprised + %p.delete(); + } +} + +function ItemData::Hazard(%data,%p,%obj,%radius) +{ +if (%p.team != %obj.team) + return 1; +if (!%data.friendly && VectorDist(%p.targetlocation,%obj.getTransform())<%radius) + return 1; + +return 0; +} + +function PlayExplosion(%pos,%data,%dir) +{ +if (%dir $= "") + %dir = "0 0 1"; +if (IsObject(%data)) + { + %p = new LinearProjectile() + { + dataBlock = %data; + initialDirection = %dir; + initialPosition = %pos; + }; + } +} + + +function GrenadeProjectile::Predict(%p,%time) +{ +//Todo: make this one +} + + +//Custon information functions (not used) +function ListSpeed(%xlist,%tlist) +{ + +if (GetWordCount(%xlist)<2) + return ""; +for (%c=0;%c 0) + return 0; +else + return -1*getWord(%awn,1); +} + +function AidPulseWaved(%pos,%time,%speed,%accel,%wave,%owner) +{ +%area = %time*%speed+1/2 * mPow(%time,2)*%accel+10; + +InitContainerRadiusSearch(%pos, %area, $TypeMasks::StaticShapeObjectType | $TypeMasks::ForceFieldObjectType ); + + + while ((%targetObject = containerSearchNext()) != 0) + { + %dist = containerSearchCurrRadDamageDist(); + %ttime = solveadist(%accel,%speed,%dist-10); + if (%ttime != 0 || %ttime < %time) + %wave.schedule(%ttime*1000,"AidEffect",%targetobject,%owner,%pos); + } +} + +function AidpulseWaver(%pos,%area,%lastar,%wave,%owner) +{ + + InitContainerRadiusSearch(%pos, %area, $TypeMasks::VehicleObjectType | $TypeMasks::PlayerObjectType |$TypeMasks::ItemObjectType | $TypeMasks::CorpseObjectType ); + + + while ((%targetObject = containerSearchNext()) != 0) + { + %dist = containerSearchCurrRadDamageDist(); + + if (%dist > %area || %dist < %lastar) + continue; + + %wave.AidEffect(%targetobject,%owner,%pos); + } + +} + +function RepairWave::AidEffect(%block,%obj,%owner,%pos) +{ +if (!isObject(%obj) || %obj.isforceField()) + return ""; +%obj.playShieldEffect("1 1 1"); +%obj.setDamageLevel(0); +} + +function CloakWave::AidEffect(%block,%obj,%owner,%pos) +{ +if (!isObject(%obj) || %obj.isforceField()) + return ""; +Cancel(%obj.uncloaksch); +%obj.setCloaked(True); +%obj.uncloaksch = %obj.schedule(60000,"setCloaked",False); +} + +function DisWave::AidEffect(%block,%obj,%owner,%Pos) +{ + +if (%obj.isRemoved || !isObject(%owner) || !isObject(%obj)) + return; +%dataBlockName = %obj.getDataBlock().getName(); +if (%dataBlockName $= "StationInventory" || %dataBlockName $= "GeneratorLarge" ||%dataBlockName $= "SolarPanel" ||%dataBlockName $= "SensorMediumPulse" ||%dataBlockName $= "SensorLargePulse") + if (%obj.deployed != true) + return; +if ($reverseDeployItem[%obj.getDataBlock().getName()] $= "") + return; +if (%obj.team != %owner.team && !(%owner.isAdmin || %owner.isSuperAdmin)) + return; +if ($Host::OnlyOwnerCascade == 1 && %obj.getOwner() != %owner && !(%owner.isAdmin || %owner.isSuperAdmin)) + return; + +%obj.getDataBlock().disassemble(%owner, %obj); // Run Item Specific code. + +} + +function ESPWave::AidEffect(%block,%obj,%owner,%pos) +{ +if (!isObject(%obj)) + return ""; +%hadsch = %obj.uncloacksch ? 1 : 0; +Cancel(%obj.uncloaksch); +if (!%obj.isforcefield()) + %obj.setCloaked(FALSE); +Cancel(%obj.unemplockschd); +if (%obj.isVehicle()) + vehemplock(%obj); +else if (%obj.isPlayer()) + PlayerEmpLock(%obj); +else if (%obj.getDatablock().maxEnergy !$= "") + { + if (%obj.getDataBlock().className $= "Generator" && %obj.lastState) + { + if (!%hadsch) + toggleGenerator(%obj,0); + %obj.unemplockschd = schedule(30000,%obj," toggleGenerator",%obj,0); + } + %obj.setEnergyLevel(0); + } +} + +function MORWave::AidEffect(%block,%obj,%owner,%pos) +{ +if (%obj.isRemoved || !isObject(%owner) || !isObject(%obj) || %obj.isPLayer() || %obj.isVehicle()) + return; +if (!(deployables.isMember(%obj))) + return; +%dataBlockName = %obj.getDataBlock().getName(); +if (%dataBlockName $= "StationInventory" || %dataBlockName $= "GeneratorLarge" ||%dataBlockName $= "SolarPanel" ||%dataBlockName $= "SensorMediumPulse" ||%dataBlockName $= "SensorLargePulse") + if (%obj.deployed != true) + return; + +if (%obj.team != %owner.team && !(%owner.isAdmin || %owner.isSuperAdmin)) + return; +if ($Host::OnlyOwnerCascade == 1 && %obj.getOwner() != %owner && !(%owner.isAdmin || %owner.isSuperAdmin)) + return; + +Cancel(%obj.unmorphsch); +%obj.unmorphsch = Schedule(30000,%obj,"ResetMorphObject",%obj); +if (%obj.morphed) +return; + +%obj.oldcenter = %obj.getEdge("0 0 0"); +%obj.oldrealsize = %obj.getrealSize(); +%obj.morphed = 1; + +%size = %owner.morphpulsesize ? %owner.morphpulsesize : 0.1; +%scale = VectorScale("1 1 1",%size); +%offset = VectorMultiply(VectorSub(%obj.getEdge("0 0 0"),%pos),%scale); +%obj.setRealSize(VectorMultiply(%obj.getRealSize(),%scale)); +%obj.setEdge(VectorAdd(%pos,%offset),"0 0 0"); +if (!%obj.isforcefield()) + %obj.startfade(500,0,0); +if (isObject(%obj.pzone)) + { + %obj.pzone.setScale(%Obj.getScale); + %obj.pzone.setTransform(%obj.getTransform()); + } +if (isObject(%obj.emitter)) + { + %obj.emitter.oldsize = %obj.getScale(); + %obj.emitter.setScale(VectorScale(%obj.emitter.getScale(),%size)); + %obj.emitter.setTransform(%obj.getTransform()); + } +if (isObject(%obj.trigger)) + { + %obj.trigger.oldsize = %obj.getScale(); + %obj.trigger.setScale(VectorScale(%obj.trigger.getScale(),%size)); + %obj.trigger.setTransform(%obj.getTransform()); + } +} + +//ESP functions + +function vehemplock(%vehicle) +{ +Cancel(%vehicle.unemplockschd); +Cancel(%vehicle.lockff.unemplockschd); +%vehicle.setFrozenState(true); +%vehicle.zapObject(); +forceFieldLock(%vehicle); +%vehicle.unemplockschd = Schedule(30000,%vehicle,"vehUnEmpLock",%vehicle); +%vehicle.lockff.unemplockschd = %vehicle.lockff.Schedule(30000,"delete"); +} + +function vehUnEmpLock(%vehicle) +{ +Cancel(%vehicle.unemplockschd); +Cancel(%vehicle.lockff.unemplockschd); +%vehicle.lockff.delete(); +%vehicle.setFrozenState(false); +} + +function PlayerEmpLock(%player) +{ +Cancel(%player.unemplockschd); +Cancel(%player.lockff.unemplockschd); +Cancel(%player.lock.unemplockschd); +if (!%player.isemped) + { + %lock = new StaticShape() + { + dataBlock = SelectionPad; + scale = "0.01 0.01 0.01"; + }; + %lock.startFade(0,0,1); + %vec = VectorNormalize(%player.getVelocity()); + %vec = (VectorLen(%vec)>0.1) ? %vec : "0 0 1"; + %center = %player.getEdge("0 0 0"); + %rot = fullrot(%vec,VectorCross(%player.getEyeVector(),%vec)); + %player.setTransform(%player.getEdge("0 0 -1") SPC %rot); + %player.setEdge(%center,"0 0 0"); + %lock.setTransform(getWords(%player.getTransform(),0,2) SPC %rot); + %lock.mountObject(%player,0); + %lock.player = %player; + %player.emplock = %lock; + %player.isemped = 1; + %player.zapObject(); + forceFieldLock(%player); + } +%player.unemplockschd = Schedule(30000,%player,"PlayerUnEmpLock",%player); +if (isObject(%player.lock)) + %player.lock.unemplockschd = %player.lock.Schedule(30000,"delete"); +if (isObject(%player.lockff)) + %player.lockff.unemplockschd = %player.lockff.Schedule(30000,"delete"); +} + +function PlayerUnEmpLock(%player) +{ +%player.isemped = 0; +Cancel(%player.unemplockschd); +Cancel(%player.lockff.unemplockschd); +Cancel(%player.lock.unemplockschd); +%player.lockff.delete(); +%player.unMount(); +if (isObject(%player.emplock)) + %player.emplock.delete(); +} + +function forceFieldLock(%obj) +{ +if (!isObject(%obj.lockff)) + { + %ff = new ForceFieldBare() { + dataBlock = DeployedForceField5; + scale = "1 1 1"; + }; + %ff.noSlow = true; + %ff.pzone.delete(); + %ff.pzone = ""; + %obj.lockff = %ff; + %ff.obj = %obj; + %ff.setScale(%obj.getRealSize()); + %ff.setTransform(%obj.getEdge("-1 -1 -1") SPC %Obj.getRotation()); + } +} + +//Morph functions + +function ResetMorphObject(%obj) +{ +Cancel(%obj.unmorphsch); +if (!%obj.isforcefield()) + %obj.startfade(500,0,0); +%obj.setRealSize(%obj.oldrealsize); +%obj.setEdge(%obj.oldcenter,"0 0 0"); +if (isObject(%obj.pzone)) + { + %obj.pzone.setScale(%Obj.getScale); + %obj.pzone.setTransform(%obj.getTransform()); + } +if (isObject(%obj.emitter)) + { + %obj.emitter.setTransform(%obj.getTransform()); + %obj.emitter.setScale(%obj.trigger.oldsize); + } +if (isObject(%obj.trigger)) + { + %obj.trigger.setTransform(%obj.getTransform()); + %obj.trigger.setScale(%obj.trigger.oldsize); + } +%obj.oldrealsize = ""; +%obj.oldcenter = ""; +%obj.morphed = ""; +} + +function resetmorphsize(%owner) +{ +%size = (getRandom()*0.9+0.1); +%dir = (Getrandom()*2 > 1); +%owner.morphpulsesize = %dir ? %size : 1+%size+getRandom()*3; +} \ No newline at end of file diff --git a/scripts/MPM/MPM_Blast.cs b/scripts/MPM/MPM_Blast.cs new file mode 100644 index 0000000..ae919ea --- /dev/null +++ b/scripts/MPM/MPM_Blast.cs @@ -0,0 +1,1635 @@ + + +//////////////////////////////////// +////////////////Nova//////////////// +//////////////////////////////////// + +datablock ParticleData(DomeRingParticle):SmokeRingParticle +{ +LifetimeMS = "12000"; +useInvAlpha = "0"; +textureName = "special/Smoke/smoke_001"; +animTexName[0] = "special/Smoke/smoke_001"; +colors[0] = "1.000000 1.000000 0.500000 1.000000"; +colors[1] = "0.900000 0.900000 0.200000 1.200000"; +colors[2] = "0.500000 0.500000 0.100000 0.500000"; +colors[3] = "0.000000 0.000000 0.100000 0.000000"; +}; + + +datablock ParticleData(FireColumParticle) { + dragCoefficient = "1"; + windCoefficient = "0"; + gravityCoefficient = "0"; + inheritedVelFactor = "0"; + constantAcceleration = "0"; + lifetimeMS = "3000"; + lifetimeVarianceMS = "0"; + spinSpeed = "0"; + spinRandomMin = "-200"; + spinRandomMax = "200"; + useInvAlpha = "0"; + animateTexture = "0"; + framesPerSec = "1"; + textureName = "special/cloudFlash"; + animTexName[0] = "special/cloudFlash"; + colors[0] = "1.000000 1.000000 0.300000 1.000000"; + colors[1] = "1.000000 0.600000 0.100000 0.200000"; + colors[2] = "1.000000 0.400000 0.000000 0.200000"; + colors[3] = "1.000000 0.200000 0.000000 0.000000"; + sizes[0] = "90"; + sizes[1] = "125"; + sizes[2] = "150"; + sizes[3] = "190"; + times[0] = "0"; + times[1] = "0.333"; + times[2] = "0.666"; + times[3] = "1"; +}; + +datablock ParticleData(FireTopParticle):FireColumParticle + { + lifetimeMS = "2000"; + }; + + + + +datablock ParticleEmitterData(DomeRingEmitter1):SmokeRing +{ +className = "ParticleEmitterData"; +ejectionPeriodMS = "1"; +periodVarianceMS = "0"; +thetaMin = "95"; +thetaMax = "85"; +ejectionOffset = "200"; +particles = "DomeRingParticle"; +}; + +datablock ParticleEmitterData(DomeRingEmitter2):SmokeRing +{ +className = "ParticleEmitterData"; +ejectionPeriodMS = "1"; +periodVarianceMS = "0"; +thetaMin = "95"; +thetaMax = "85"; +ejectionOffset = "300"; +particles = "DomeRingParticle"; + +}; + +datablock ParticleEmitterData(FireColumEmitter) { + className = "ParticleEmitterData"; + ejectionPeriodMS = "1"; + periodVarianceMS = "0"; + ejectionVelocity = "5"; + velocityVariance = "0"; + ejectionOffset = "50"; + thetaMin = "95"; + thetaMax = "85"; + phiReferenceVel = "0"; + phiVariance = "360"; + overrideAdvance = "0"; + orientParticles = "0"; + orientOnVelocity = "1"; + particles = "FireColumParticle"; + lifetimeMS = "-1"; + lifetimeVarianceMS = "0"; + useEmitterSizes = "0"; + useEmitterColors = "0"; + overrideAdvances = "0"; +}; + +datablock ParticleEmitterData(FireTopEmitter):FireColumEmitter +{ + particles = "FireTopParticle"; + thetaMin = "90"; + thetaMax = "90"; + ejectionOffset = "0"; + ejectionVelocity = "50"; + velocityVariance = "50"; +}; + +datablock SeekerProjectileData(DomeStreamProjectile) +{ + projectileShapeName = "turret_muzzlepoint.dts"; + explosion = "TacNukeFireballFireExp";//"GrenadeExplosion"; + velInheritFactor = 1.0; + + baseEmitter = FireTopEmitter; + delayEmitter = FireColumEmitter; + + lifetimeMS = 8000; + muzzleVelocity = 0.1; + maxVelocity = 500; + acceleration = 50; +}; + + + +function dome(%pos,%time,%inside) +{ +if (!%time) + %time = 60000; +shockwave(%pos,%nrm,"InitialProjectile"); +//shockwave(%pos,%nrm,"InitialProjectile"); ?? +//shockwave(%pos,%nrm,"InitialProjectile"); +//shockwave(%pos,%nrm,"InitialProjectile"); +for (%i=0; %i < 10;%i++) + { + %nrm = mCos(%i*$pi/10) SPC mSin(%i*$pi/10) SPC 0; + shockwave(VectorAdd(%pos,VectorScale(%nrm,49)),%nrm,"DomeProjectile"); + shockwave(VectorAdd(%pos,VectorScale(%nrm,-49)),VectorScale(%nrm,-1),"DomeProjectile"); + } +domeColum(%pos,"0 0 1"); +domeColum(%pos,"0 0 -1"); + +%ang = GetRandom()*2*$pi; +%nrm = VectorNormalize(mCos(%ang) SPC mSin(%ang) SPC 2); +Schedule(100,0,"whiteout",%pos,500,2000); +schedule(4000,0,"darkhole",%pos,%nrm,%time,"",%inside); +schedule(2000,0,"holeDebris",%pos); +Schedule(%time,0,"whiteout",%pos,1000,2500); +schedule(%time,0,"tube",%pos,%nrm,%ang); +schedule(%time,0,"delBHPieces",%pos); //remove sucked pieces. +} + +function domeColum(%pos,%nrm) +{ +%speed = VectorScale(%nrm,200); +%obj = new Item() + { + className = Item; + dataBlock = MpmLaucher; + }; +%obj.mountimage(MpmLauchPoint,0); +%obj.setTransform(%pos); +%obj.setVelocity(%speed); +%speed = %obj.getVelocity(); +%p = new SeekerProjectile() + { + datablock = DomeStreamProjectile; + initialDirection = VectorScale(%nrm,-1); + initialPosition = %obj.getWorldBoxCenter(); + SourceObject = %obj; + SourceSlot = 0; + }; +%p.StartVelocity = %speed; +%p.createtime=getSimTime(); +%obj.delete(); + +Schedule(0,%p,"domering",%p); +Schedule(4000,%p,"domering",%p); +} + +function domering(%p) +{ +shockwave(%p.getTransForm(),%p.InitialDirection,"DomeRingProjectile"); +} + + + +//////////////////////////////////// +/////////////BlackHole////////////// +//////////////////////////////////// + + +//Hole +//GravStar +//DiskArm +//Disk +//Vent +//Dust + +datablock ParticleData(DHHoleParticle) +{ + dragCoeffiecient = 0.0; + gravityCoefficient = 0.0; + inheritedVelFactor = 0.0; + + lifetimeMS = 6000; + lifetimeVarianceMS = 0; + spinSpeed = "0"; + spinRandomMin = 0.0; + spinRandomMax = 0.0; + windcoefficient = 0; + textureName = "skins/jetpackFlare"; + UseInvAlpha = True; + colors[0] = "0.0 0.0 0.0 0.0"; + colors[1] = "0.0 0.0 0.0 1.0"; + colors[2] = "0.0 0.0 0.0 1.0"; + colors[3] = "0.0 0.0 0.0 0.0"; + + sizes[0] = 800; + sizes[1] = 800; + sizes[2] = 800; + sizes[3] = 800; + + times[0] = 0.25; + times[1] = 0.5; + times[2] = 0.75; + times[3] = 1; + +}; + +datablock ParticleData(DHGravStarParticle) +{ + dragCoeffiecient = 1.0; + gravityCoefficient = 0.0; + inheritedVelFactor = -1.0; + + lifetimeMS = 8750; + lifetimeVarianceMS = 0; + constantAcceleration = "-100"; + spinRandomMin = 0.0; + spinRandomMax = 0.0; + windcoefficient = 0; + textureName = "skins/jetpackflare_bio"; + + colors[0] = "1 1 1 0"; + colors[1] = "1 1 0.7 1"; + colors[2] = "1 1 0 1"; + colors[3] = "1 1 1 0"; + + sizes[0] = 20; + sizes[1] = 15; + sizes[2] = 10; + sizes[3] = 5; + + times[0] = 0.1; + times[1] = 0.5; + times[2] = 0.9; + times[3] = 1; + +}; + + +datablock ParticleData(DHInvHoleParticle) +{ + dragCoeffiecient = 0.0; + gravityCoefficient = 0.0; + inheritedVelFactor = 0.0; + + lifetimeMS = 6000; + lifetimeVarianceMS = 0; + spinSpeed = "0"; + spinRandomMin = 0.0; + spinRandomMax = 0.0; + windcoefficient = 0; + textureName = "skins/jetpackFlare"; + UseInvAlpha = false; + colors[0] = "1.0 1.0 1.0 0.0"; + colors[1] = "1.0 1.0 1.0 1.0"; + colors[2] = "1.0 1.0 1.0 1.0"; + colors[3] = "1.0 1.0 1.0 0.0"; + + sizes[0] = 800; + sizes[1] = 800; + sizes[2] = 800; + sizes[3] = 800; + + times[0] = 0.25; + times[1] = 0.5; + times[2] = 0.75; + times[3] = 1; + +}; + +datablock ParticleData(DHInvGravStarParticle) +{ + dragCoeffiecient = 1.0; + gravityCoefficient = 0.0; + inheritedVelFactor = -1.0; + + lifetimeMS = 8750; + lifetimeVarianceMS = 0; + constantAcceleration = "-100"; + spinRandomMin = 0.0; + spinRandomMax = 0.0; + windcoefficient = 0; + textureName = "skins/jetpackflare_bio"; + + colors[0] = "1 1 1 0"; + colors[1] = "1 1 0.7 1"; + colors[2] = "1 1 0 1"; + colors[3] = "1 1 1 0"; + + sizes[0] = 20; + sizes[1] = 15; + sizes[2] = 10; + sizes[3] = 5; + + times[0] = 0.1; + times[1] = 0.5; + times[2] = 0.9; + times[3] = 1; + +}; + + + +datablock ParticleData(DHDiskArmParticle):DHGravStarParticle +{ + lifetimeMS = 4900; + colors[0] = "1 0.5 0.5 0.5"; + colors[1] = "1 0.8 0.5 1"; + colors[2] = "1 1 0.5 1"; + colors[3] = "1 1 1 0"; + + + sizes[0] = 20; + sizes[1] = 15; + sizes[2] = 10; + sizes[3] = 5; +}; + + + +datablock ParticleData(DHDiskParticle) +{ + dragCoeffiecient = 2.0; + gravityCoefficient = 0.0; + inheritedVelFactor = 0.0; + + lifetimeMS = 12500; + lifetimeVarianceMS = 0; + constantAcceleration = 0; + spinRandomMin = 0.0; + spinRandomMax = 0.0; + windcoefficient =0; + textureName = "skins/jetpackflare_bio"; + + + sizes[0] = 20; + sizes[1] = 30; + sizes[2] = 40; + sizes[3] = 50; + + colors[0] = "1 0.5 0.5 0.5"; + colors[1] = "1 1 1 1"; + colors[2] = "1 0.5 0.5 1"; + colors[3] = "1 0 1 0"; + + + times[0] = 0.1; + times[1] = 0.5; + times[2] = 0.75; + times[3] = 1; + +}; + +datablock ParticleData(DHVentParticle):DHDiskParticle +{ + dragCoeffiecient = 0.0; + constantAcceleration = "0.1"; + colors[0] = "1 1 1 1"; + colors[1] = "1 1 1 1"; + colors[2] = "1 0.5 0.5 1"; + colors[3] = "1 0 1 0"; + + + sizes[0] = 20; + sizes[1] = 15; + sizes[2] = 10; + sizes[3] = 5; +}; + + +datablock ParticleData(DHDustParticle) +{ + dragCoeffiecient = 1.0; + gravityCoefficient = 0.0; + inheritedVelFactor = -1.0; + + lifetimeMS = 10500; + lifetimeVarianceMS = 0; + constantAcceleration = "-100"; + spinRandomMin = 0.0; + spinRandomMax = 0.0; + windcoefficient = 0; + useInvAlpha = true; + spinRandomMin = -90.0; + spinRandomMax = 500.0; + textureName = "particleTest"; + colors[0] = "0.46 0.36 0.26 1"; + colors[1] = "0.46 0.46 0.36 0.9"; + colors[2] = "0.46 0.46 0.36 0.7"; + sizes[0] = 15; + sizes[1] = 10; + sizes[2] = 5; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; +}; + + +datablock ParticleEmitterData(DHHoleEmitter) +{ + lifetimeMS = 10; + ejectionPeriodMS = 50; + periodVarianceMS = 0; + + ejectionVelocity = 0.1; + velocityVariance = 0.1; + ejectionoffset = 10; + phiReferenceVel = "0"; + phiVariance = "360"; + thetaMin = 0.0; + thetaMax = 180.0; + spinRandomMin = "-200"; + spinRandomMax = "200"; + + orientParticles = true; + orientOnVelocity = false; + + particles = "DHHoleParticle"; + predietime = 6000; +}; + + +datablock ParticleEmitterData(DHGravStarEmitter) +{ + lifetimeMS = 10; + ejectionPeriodMS = 10; + periodVarianceMS = 0; + + ejectionVelocity = 0.1; + velocityVariance = 0 ; + ejectionoffset = 400; + phiReferenceVel = "0"; + phiVariance = "360"; + thetaMin = 0.0; + thetaMax = 180.0; + spinRandomMin = "-200"; + spinRandomMax = "200"; + + orientParticles = true; + orientOnVelocity = true; + + particles = DHGravStarParticle; + predietime = 12500; +}; + + +datablock ParticleEmitterData(DHInvHoleEmitter) +{ + lifetimeMS = 10; + ejectionPeriodMS = 50; + periodVarianceMS = 0; + + ejectionVelocity = 0.1; + velocityVariance = 0.1; + ejectionoffset = 10; + phiReferenceVel = "0"; + phiVariance = "360"; + thetaMin = 0.0; + thetaMax = 180.0; + spinRandomMin = "-200"; + spinRandomMax = "200"; + + orientParticles = true; + orientOnVelocity = false; + + particles = "DHInvHoleParticle"; + predietime = 6000; +}; + + +datablock ParticleEmitterData(DHInvGravStarEmitter) +{ + lifetimeMS = 10; + ejectionPeriodMS = 10; + periodVarianceMS = 0; + + ejectionVelocity = 0.1; + velocityVariance = 0 ; + ejectionoffset = 10; + phiReferenceVel = "0"; + phiVariance = "360"; + thetaMin = 0.0; + thetaMax = 180.0; + spinRandomMin = "-200"; + spinRandomMax = "200"; + + orientParticles = true; + orientOnVelocity = true; + + particles = DHInvGravStarParticle; + predietime = 12500; +}; + + +datablock ParticleEmitterData(DHDiskArmEmitter) +{ + lifetimeMS = 10; + ejectionPeriodMS = 20; + periodVarianceMS = 0; + + ejectionVelocity = 0.1; + velocityVariance = 0 ; + ejectionoffset = 150; + phiReferenceVel = "20"; + phiVariance = "30"; + thetaMin = 90.0; + thetaMax = 90.0; + spinRandomMin = "-200"; + spinRandomMax = "200"; + + orientParticles = true; + orientOnVelocity = true; + + particles = DHDiskarmParticle; + predietime = 13000; +}; + +datablock ParticleEmitterData(DHDiskEmitter) +{ + lifetimeMS = 10; + ejectionPeriodMS = 30; + periodVarianceMS = 0; + + ejectionVelocity = 0.1; + velocityVariance = 2; + ejectionoffset = 150; + phiReferenceVel = "20"; + phiVariance = "50"; + thetaMin = 90.0; + thetaMax = 90.0; + spinRandomMin = "-200"; + spinRandomMax = "200"; + + orientParticles = true; + orientOnVelocity = true; + + particles = DHDiskParticle; + predietime = 13000; +}; + + + +datablock ParticleEmitterData(DHDiskEmitter2) +{ + lifetimeMS = 10; + ejectionPeriodMS = 30; + periodVarianceMS = 0; + + ejectionVelocity = 0.1; + velocityVariance = 2; + ejectionoffset = 135; + phiReferenceVel = "20"; + phiVariance = "50"; + thetaMin = 90.0; + thetaMax = 90.0; + spinRandomMin = "-200"; + spinRandomMax = "200"; + + orientParticles = true; + orientOnVelocity = true; + + particles = DHDiskParticle; + predietime = 13000; +}; + + + + +datablock ParticleEmitterData(DHVentEmitter) +{ + lifetimeMS = 10; + ejectionPeriodMS = 30; + periodVarianceMS = 0; + + ejectionVelocity = 25; + velocityVariance = 0; + ejectionoffset = 50; + phiReferenceVel = "0"; + phiVariance = "360"; + thetaMin = 0.0; + thetaMax = 5.0; + spinRandomMin = "-200"; + spinRandomMax = "200"; + + orientParticles = true; + orientOnVelocity = true; + + particles = DHVentParticle; + predietime = 3000; +}; + + +datablock ParticleEmitterData(DHDustEmitter) +{ + lifetimeMS = 10; + ejectionPeriodMS = 20; + periodVarianceMS = 0; + + ejectionVelocity = 0.1; + velocityVariance = 0 ; + ejectionoffset = 600; + phiReferenceVel = "20"; + phiVariance = "20"; + thetaMin = 15.0; + thetaMax = 20.0; + spinRandomMin = "-200"; + spinRandomMax = "200"; + + orientParticles = false; + orientOnVelocity = false; + + particles = DHDustParticle; + predietime = 13000; +}; + + + +datablock ParticleData(ArcParticle) { + dragCoeffiecient = 0.0; + gravityCoefficient = -0.2; + inheritedVelFactor = 0.0; + + lifetimeMS = 2000; + lifetimeVarianceMS = 0; + + textureName = "particleTest"; + + useInvAlpha = false; + spinRandomMin = -160.0; + spinRandomMax = 160.0; + + animateTexture = true; + framesPerSec = 15; + + animTexName[0] = "special/Explosion/exp_0016"; + animTexName[1] = "special/Explosion/exp_0018"; + animTexName[2] = "special/Explosion/exp_0020"; + animTexName[3] = "special/Explosion/exp_0022"; + animTexName[4] = "special/Explosion/exp_0024"; + animTexName[5] = "special/Explosion/exp_0026"; + animTexName[6] = "special/Explosion/exp_0028"; + animTexName[7] = "special/Explosion/exp_0030"; + animTexName[8] = "special/Explosion/exp_0032"; + + colors[0] = "1.0 0.7 0.5 1.0"; + colors[1] = "1.0 0.5 0.2 1.0"; + colors[2] = "1.0 0.25 0.1 0.0"; + sizes[0] = 2.0; + sizes[1] = 1.0; + sizes[2] = 0.5; + times[0] = 0.0; + times[1] = 0.2; + times[2] = 1.0; +}; + +datablock ParticleEmitterData(ArcEmitter) { + ejectionPeriodMS = 5; + periodVarianceMS = 1; + + ejectionVelocity = 0.25; + velocityVariance = 0.0; + + thetaMin = 90.0; + thetaMax = 90.0; + + particles = "ArcParticle"; +}; + + +datablock SeekerProjectileData(ArcProjectile3) +{ + projectileShapeName = "turret_muzzlepoint.dts"; + explosion = PlasmaBoltExplosion; + splash = PlasmaSplash; + velInheritFactor = 1.0; + + + baseEmitter = ArcEmitter; + delayEmitter = DebrisFireEmitter; + + lifetimeMS = -1; + muzzleVelocity = 0.1; + maxVelocity = 500; + acceleration = 5; +}; + +datablock SeekerProjectileData(ArcProjectile2) +{ + projectileShapeName = "turret_muzzlepoint.dts"; + explosion = PlasmaBoltExplosion; + splash = PlasmaSplash; + velInheritFactor = 1.0; + + + baseEmitter = DebrisFireEmitter; + delayEmitter = VSmokeSpikeEmitter; + + lifetimeMS = -1; + muzzleVelocity = 0.1; + maxVelocity = 500; + acceleration = 5; +}; + + +function darkhole(%pos,%nrm,%time,%destination,%inside) +{ +if (%nrm $= "" || vAbs(%nrm) $= "0 0 1") + { + %nrm = "0 0 1"; + %rot = "1 0 0 0"; + %rot2 = "1 0 0 3.14"; + } +else + { + %rot = fullrot(%nrm,"0 0 1"); + %rot2 = fullrot(VectorScale(%nrm,-1),"0 0 1"); + } + +%mainGroup = nameToID("MissionCleanup/HoleGroup"); + if (%mainGroup <= 0) + { + %mainGroup = new SimGroup("HoleGroup"); + MissionCleanup.add(%Group); + } +%group = new SimGroup("Hole"@ %maingroup.holes); + +//If there's no general destination transform, make one. +//Destination is an offset so two b-holes near eachother will have destinations near eachother. +if ($destination $= "") + { + if (vAbs(%nrm) $= "0 0 1") + %group.destination = VectorAdd(VectorScale(VectorNormalize(GetRandom()-0.5 SPC GetRandom()-0.5),GetRandom()*50000+10000),%pos); + else + %group.destination = VectorAdd(VectorScale(VectorNormalize(getWords(%nrm,0,1)),GetRandom()*50000+10000),%pos); + $destination = %group.destination; + } + +%group.destination = VectorAdd($destination,%pos); +%group.inside = %inside; +%group.rot = %rot; +%group.rot2 = %rot2; +%group.pos = %pos; +%group.nrm = %nrm; +%group.syncTime = GetSimTime(); +if ((getWord(%pos,2)-getTerrainHeight(%pos))<400) + %group.dust = 1; +//echo("dust is:" SPC %group.dust); +%maingroup.add(%group); +%maingroup.holes++; +%killtime = GetSimTime()+%time; +%group.darkholeFase(0); +if (!%time || %time > 4500) +%group.schedule(4500,"darkholeFase",1); +if (!%time || %time > 9000) +%group.schedule(9000,"darkholeFase",2); +if (!%time || %time > 13500) +%group.schedule(13500,"darkholeFase",3); +if (%time) + { + %group.killtime = GetSimTime()+%time; + %group.schedule(%time-13000,"HoleStop"); + } +return %group; +} + +function SimGroup::DarkHoleFase(%group,%fase) +{ +if (%group.stopped) + return ""; +%pos = %group.pos; +%pos2 = %group.destination; +//echo(%pos2); +%rot = %group.rot; +%rot2 = %group.rot2; +%inside= %group.inside; +if (%fase == 0) + { + if (!%inside) + %p1 =CreateEmitter(%pos,DHDiskEmitter,%rot); + %p2 = CreateEmitter(%pos,DHGravStarEmitter,%rot); + if (%group.dust) + %p3 = CreateEmitter(%pos,DHDustEmitter,"1 0 0 3.14"); + %p4 = CreateEmitter(%pos,DHDiskArmEmitter,%rot); + } +else if (%fase == 1) + { + if (!%inside) + %p1 =CreateEmitter(%pos,DHDiskEmitter2,%rot); + %p2 =CreateEmitter(%pos,DHDiskArmEmitter,%rot); + %p3 = %group.invhole = CreateEmitter(%pos2,DHInvHoleEmitter,%rot); + %p4 = CreateEmitter(%pos2,DHInvGravStarEmitter,%rot); + } +else if (%fase == 2) + { + %p1 = %group.hole = CreateEmitter(%pos,DHHoleEmitter,%rot); + %p1.holesuck(); + %p2 = CreateEmitter(%pos,DHDiskARmEmitter,%rot); + if (%group.dust) + %p3 = CreateEmitter(%pos,DHDustEmitter,"1 0 0 3.14"); + if (!%inside) + %p4 = CreateEmitter(%pos,DHDiskEmitter,%rot); + } +else if (%fase == 3) + { + %p1 =CreateEmitter(%pos,DHDiskArmEmitter,%rot); + if (!%inside) + %p2 =CreateEmitter(%pos,DHDiskEmitter2,%rot); + %p3 =CreateEmitter(%pos,DHVentEmitter,%rot); + %p4 =CreateEmitter(%pos,DHVentEmitter,%rot2); + } +if (%p1) + { + %p1.fase = %fase; + %group.add(%p1); + } +if (%p2) + { + %p2.fase = %fase; + %group.add(%p2); + } +if (%p3) + { + %p3.fase = %fase; + %group.add(%p3); + } +if (%p4) + { + %p4.fase = %fase; + %group.add(%p4); + } + + +} + +function SimGroup::HoleStop(%group) +{ +%group.stopped = 1; +for (%i=0; %i < %group.getCount();%i++) + { + %obj = %group.getObject(%i); + %time = %obj.Emitter.predietime; + %obj.schedule(13000-%time,"delete"); + } +%group.schedule(14000,"delete"); +} + +function SimGroup::HoleSeqStop(%group,%seq) +{ +for (%i=0;%i<%group.getCount();%i++) + { + if (%group.getObject(%i).fase==%seq) + %group.getObject(%i).delete(); + } +if (%seq == 3) + %group.delete(); +} + +function holemovenrm() +{ +Cancel($holemovenrm); +for (%i=0;%i= 20) + continue; + %dist = containerSearchCurrRadDamageDist(); + %distPct = %dist / %area; + if (!%targetobject.HasEye(%pos)&& %dist >10) + continue; + + if (%area < 2000) + %power = %area; + else + %power = Limit(500 - %area,0,200); + + if (%dist < 50) //Shockwave + { + %force = (%power/100)*%targetobject.getDatablock().mass; + %damage = Limit(100/%dist,0,100); + %upvec = "0 0 1"; + } + else + { + %force = (%power/100)*%targetobject.getDatablock().mass; + %damage = 0; + %upvec = ""; + } + + %tgtPos = %targetObject.getWorldBoxCenter(); + %vec = VectorNormalize(VectorSub(%pos,%tgtpos)); + %nForce = Limit(2000-%dist,0)*(%targetobject.getDatablock().mass/45); + %rotmod = VectorCross(%group.nrm,%vec); + %forceVector = VectorAdd(vectorScale(%vec, %nForce),%rotmod); + if((%targetObject.getType() & $TypeMasks::StaticShapeObjectType) && !(%targetObject.getType() & ($TypeMasks::VehicleObjectType | $TypeMasks::PlayerObjectType))&& %moved < 20) + { + if (!$host::invincibleDeployables) + { + if (%group.isMember(%targetobject)&& GetRandom()*%moved<5 && (!%targetobject.isSticky() || %dist < 50)) + { + if (%dist<10) + { + arcDebris(%pos); + %targetObject.SetDamageState("Destroyed"); + } + %ttime = GetRandom()*400+100; + %targetObject.Schedule(%ttime,"SuckTo",%pos); + %targetObject.getDataBlock().damageObject( %targetObject, 0,pos( %targetObject),((2000-%dist)/200000),$DamageType::Explosion); + %moved++; + } + } + } + else + { + if (%damage>0.01) + { + + if (GetRandom()*100 < 25+%mod) + { + %pos2 = VectorAdd(pos(%obj.getGroup().invhole),VectorSub(%tgtpos,%pos)); + %targetObject.SetTransform(%pos2 SPC %targetObject.GetRotation()); + } + else + { + %targetObject.getDataBlock().damageObject( %targetObject, %obj,pos( %targetObject),%damage,$DamageType::Explosion); + } + } + + + + } + if (!%targetObject.deployed && !($host::invinciblearmors && (%targetObject.getType() & $TypeMasks::PlayerObjectType))) + %targetObject.applyImpulse(pos(%targetObject), %forceVector); + } + InitContainerRadiusSearch(pos(%obj.getGroup().invhole), 50, $TypeMasks::VehicleObjectType | $TypeMasks::PlayerObjectType| $TypeMasks::ItemObjectType | $TypeMasks::CorpseObjectType); + + while ((%targetObject = containerSearchNext()) != 0) + { + %tgtPos = %targetObject.getWorldBoxCenter(); + %vec = VectorNormalize(VectorSub(pos(%obj.getGroup().invhole),%tgtpos)); + %nForce = Limit(2000-%dist,0)*(%targetobject.getDatablock().mass/45); + %rotmod = VectorCross(%group.nrm,%vec); + %forceVector = vectorScale(%vec, -1*%nForce); + %targetObject.applyImpulse(pos(%targetObject), %forceVector); + } + +%obj.sucksh = %obj.schedule(500,"HoleSuck"); +} + +function GameBase::HasEye(%obj,%pos) +{ +%mask = $TypeMasks::StaticShapeObjectType | $TypeMasks::ForceFieldObjectType | $TypeMasks::InteriorObjectType; +%res = containerRayCast(%pos,%obj.getWorldBoxCenter(),%mask, %obj); +return !isObject(%res); +} + +function GameBase::isSticky(%obj) +{ +if (IsObject(%obj.Dsurface) && (%obj.dSurface.getType() & $TypeMasks::StaticShapeObjectType)) + { + if (%obj.Dsurface.getDataBlock().className $= "floor") + return 1; + if (%obj.Dsurface.getDataBlock().className $= "mSpine") + return 1; + } +if (%obj.getDataBlock().className $= "floor") + return 1; +if (%obj.getDataBlock().className $= "mspine") + return 1; +return 0; +} + +function GameBase::SuckTo(%obj,%pos) +{ +%opos = %obj.getWorldBoxCenter(); +%orot = %obj.getRotation(); +%dir = VectorNormalize(VectorSub(%pos,%opos)); +%dist = VectorDist(%pos,%opos); +%head = VectorNormalize(topvec(%obj.getRealSize())); +%scaler = VectorAdd(VectorScale(%head,1.01),VectorScale(InvFace(%head),0.99)); +%mForce = Limit(mpow(2000-%dist,0.5),0); +%oldup = Realvec(%obj,"0 0 1"); +%oldfo = Realvec(%obj,"1 0 0"); +if (%head $= "1 0 0") + { + %newfo = %dir; + %newup = VectorCross(VectorCross(%dir,%oldup),%dir); + } +else if (%head $= "0 1 0") + { + %newfo = VectorCross(%dir,%oldup); + %newup = VectorCross(%oldfo,%dir); + } +else + { + %newup = %dir; + %newfo = VectorCross(VectorCross(%dir,%oldfo),%dir); + } +%newup = VectorScale(%newup,0.05); +%newfo = VectorScale(%newfo,0.05); +%newrot = FullRot(VectorNormalize(VectorAdd(%oldup,%newup)),VectorNormalize(VectorAdd(%oldfo,%newfo))); +%newscale = VectorMultiply(%obj.getScale(),%scaler); +%obj.SetRotation(%newrot); +%obj.setScale(%newscale); +%newpos = VectorAdd(%obj.getEdge(VectorScale(%head,0)),VectorScale(%dir,(2000-%dist)/200)); +%obj.setEdge(%newpos,VectorScale(%head,0)); +%obj.wassucked = 1; +} + +function delBHPieces(%pos) { + + %randomTime = 10000; + %group = nameToID("MissionCleanup/Deployables"); + %count = %group.getCount(); + for(%i=0;%i<%count;%i++) { + %obj = %group.getObject(%i); + if (%obj.wassucked) { + %time = getRandom() * %randomTime; + if (%pos !$= "") + %time = VectorDist(%pos,%obj.getTransform())*1000/60; + %obj.getDataBlock().schedule(%time,"disassemble",%plyr,%obj); // Run Item Specific code. + %deleted++; + } + else + %checked++; + } + + return %randomTime; +} + + +/////////////////////////////////// +///////////////Rift//////////////// +/////////////////////////////////// + +datablock ParticleData(SmokeRingParticle) { + dragCoefficient = "0.6"; + windCoefficient = "0"; + gravityCoefficient = "-0.1"; + inheritedVelFactor = "0"; + constantAcceleration = "0"; + lifetimeMS = "5000"; //11000 + lifetimeVarianceMS = "0"; + spinSpeed = "0"; + spinRandomMin = "-30"; + spinRandomMax = "30"; + useInvAlpha = "0"; + animateTexture = "0"; + framesPerSec = "1"; + textureName = "special/cloudFlash"; + animTexName[0] = "special/cloudFlash"; + colors[0] = "0.950000 0.950000 1.000000 0.000000"; + colors[1] = "0.800000 0.800000 0.950000 0.200000"; + colors[2] = "0.800000 0.800000 0.950000 0.100000"; + colors[3] = "0.550000 0.550000 0.950000 0.000000"; + sizes[0] = "10"; + sizes[1] = "20"; + sizes[2] = "20"; + sizes[3] = "20"; + times[0] = "0"; + times[1] = "0.1"; + times[2] = "0.7"; + times[3] = "1"; +}; + + + +datablock ParticleEmitterData(SmokeRing) { + className = "ParticleEmitterData"; + ejectionPeriodMS = "1"; + periodVarianceMS = "0"; + ejectionVelocity = "5"; + velocityVariance = "0"; + ejectionOffset = "200"; + thetaMin = "95"; + thetaMax = "85"; + phiReferenceVel = "0"; + phiVariance = "360"; + overrideAdvance = "0"; + orientParticles = "0"; + orientOnVelocity = "1"; + particles = "SmokeRingParticle"; + lifetimeMS = "-1"; + lifetimeVarianceMS = "0"; + useEmitterSizes = "0"; + useEmitterColors = "0"; + overrideAdvances = "0"; +}; + + +datablock LinearProjectileData(SmokeProjectile) { + className = "LinearProjectileData"; + projectileShapeName = "turret_muzzlepoint.dts"; + baseEmitter = "mpmFlareEmitter1"; + delayEmitter = "SmokeRing"; + Explosion = ""; + hasLight = "1"; + lightRadius = "20"; + lightColor = "0.500000 0.500000 1.000000 1.000000"; + dryVelocity = "12"; + wetVelocity = "12"; + fizzleTimeMS = "12000"; + lifetimeMS = "12000"; + explodeOnDeath = "1"; +}; + + +function tube(%pos,%nrm,%ang) +{ +%pos2 = %pos; +CreateLifeEmitter(%pos,mpmFlareEmitter1,6000); +Schedule(6000,0,"smoketube",%pos,%nrm); +Schedule(6000,0,"smoketube",%pos,VectorScale(%nrm,-1)); +//Schedule(3000,0,"shockwave",VectorAdd(%pos,VectorScale(%nrm,-100)),%nrm,"HugeShProjectile"); +Schedule(3000,0,"shockwave",VectorAdd(%pos,VectorScale(%nrm,-100)),VectorNormalize(mCos(%ang) SPC mSin(%ang) SPC 1.5),"HugeShProjectile"); +Schedule(3000,0,"shockwave",VectorAdd(%pos,VectorScale(%nrm,-100)),VectorNormalize(mCos(%ang) SPC mSin(%ang) SPC 3),"HugeShProjectile"); +for (%i=0; %i < 20;%i++) + { + %pos = VectorAdd(%pos,VectorScale(%nrm,5)); + %pos2 = VectorAdd(%pos2,VectorScale(%nrm,-5)); + Schedule(%i*400,0,"shockwave",%pos,%nrm); + Schedule(%i*400,0,"shockwave",%pos2,VectorScale(%nrm,-1)); + } +} + +function smoketube(%pos,%nrm) +{ +%p1 = new LinearProjectile() + { + dataBlock = SmokeProjectile; + initialDirection = %nrm; + initialPosition = %pos; + }; +} + + +/////////////////////////// +/////////ShockWaves//////// +/////////////////////////// + +datablock ShockwaveData(BaseShockWave) { + className = "ShockwaveData"; + scale = "1 1 1"; + delayMS = "0"; + delayVariance = "0"; + lifetimeMS = "12000"; + lifetimeVariance = "0"; + width = "5"; + numSegments = "20"; + numVertSegments = "10"; + velocity = "-30"; + height = "20"; + verticalCurve = "5"; + acceleration = "5"; + times[0] = "0"; + times[1] = "0.5"; + times[2] = "1"; + times[3] = "1"; + colors[0] = "0.000000 0.000000 0.500000 0.100000"; //1.0 0.9 0.9 + colors[1] = "0.500000 0.500000 1.000000 1.000000"; //0.6 0.6 0.6 + colors[2] = "0.500000 0.500000 1.000000 0.100000"; //0.6 0.6 0.6 + colors[3] = "1.000000 1.000000 1.000000 1.000000"; + texture[0] = "special/shockwave4"; + texture[1] = "special/gradient"; + texWrap = "7"; + is2D = "0"; + mapToTerrain = "0"; + orientToNormal = "1"; + renderBottom = "1"; + renderSquare = "0"; +}; + + +datablock ShockwaveData(DomeShockWave) { + className = "ShockwaveData"; + delayMS = "0"; + delayVariance = "0"; + lifetimeMS = "8000"; + lifetimeVariance = "0"; + width = "5"; + numSegments = "80"; + numVertSegments = "10"; + velocity = "-200"; + height = "62"; + verticalCurve = "2.5"; + acceleration = "50"; + times[0] = "0"; + times[1] = "0.5"; + times[2] = "1"; + times[3] = "1"; + colors[0] = "1.000000 1.000000 0.500000 0.100000"; //1.0 0.9 0.9 + colors[1] = "1.000000 1.000000 0.500000 1.000000"; //0.6 0.6 0.6 + colors[2] = "1.000000 1.000000 0.500000 0.100000"; //0.6 0.6 0.6 + colors[3] = "1.000000 1.000000 1.000000 1.000000"; + texture[0] = "special/whitenoAlpha"; + texture[1] = "special/whitenoAlpha"; + texWrap = "7"; + orientToNormal = "1"; + renderBottom = "1"; + mapToTerrain = "0"; +}; + +datablock ShockwaveData(HugeShockWave) + { + className = "ShockwaveData"; + delayMS = "0"; + delayVariance = "0"; + lifetimeMS = "20000"; + lifetimeVariance = "0"; + width = "500"; + numSegments = "80"; + numVertSegments = "10"; + velocity = "60"; + height = "40"; + verticalCurve = "10"; + acceleration = "-4"; + times[0] = "0"; + times[1] = "0.1"; + times[2] = "0.9"; + times[3] = "1"; + colors[0] = "0.000000 0.000000 0.500000 0.100000"; //1.0 0.9 0.9 + colors[1] = "0.500000 0.500000 1.000000 1.000000"; //0.6 0.6 0.6 + colors[2] = "0.500000 0.500000 1.000000 1.000000"; //0.6 0.6 0.6 + colors[3] = "1.000000 1.000000 1.000000 0.000000"; + texture[0] = "special/shockwave4"; + texture[1] = "special/gradient"; + texWrap = "7"; + orientToNormal = "1"; + renderBottom = "1"; + mapToTerrain = "0"; +}; + + + +datablock ShockwaveData(InitialShockWave) { + className = "ShockwaveData"; + scale = "1 1 1"; + delayMS = "0"; + delayVariance = "0"; + lifetimeMS = "11000"; + lifetimeVariance = "0"; + width = "20"; + numSegments = "240"; + numVertSegments = "12"; + velocity = "150"; + height = "100"; + verticalCurve = "0.95"; + acceleration = "0"; + times[0] = "0"; + times[1] = "0.5"; + times[2] = "1"; + times[3] = "1"; + colors[0] = "1.000000 1.000000 0.300000 1.000000"; //1.0 0.9 0.9 + colors[1] = "1.000000 0.600000 0.100000 0.600000"; //0.6 0.6 0.6 + colors[2] = "1.000000 0.400000 0.000000 0.000000"; //0.6 0.6 0.6 + colors[3] = "1.000000 1.000000 1.000000 1.000000"; + texture[0] = "special/shockwave4"; + texture[1] = "special/gradient"; + texWrap = "7"; + is2D = "0"; + mapToTerrain = "1"; + orientToNormal = "0"; + renderBottom = "1"; + renderSquare = "0"; +}; + +datablock ExplosionData(BaseExplosion) + { + className = "ExplosionData"; + particleDensity = "10"; + particleRadius = "1"; + explosionScale = "1 1 1"; + playSpeed = "1"; + Shockwave = "BaseShockWave"; + shockwaveOnTerrain = "0"; + lifetimeMS = "1000"; + }; + +datablock ExplosionData(DomeExplosion):BaseExplosion + { + Shockwave = "DomeShockWave"; + }; + +datablock ExplosionData(HugeShExplosion):BaseExplosion + { + Shockwave = "HugeShockWave"; + }; + +datablock ExplosionData(InitialExplosion):BaseExplosion + { + Shockwave = "InitialShockWave"; + }; + +datablock ExplosionData(DomeRingExplosion) + { + emitter[0] = "DomeRingEmitter2"; + emitter[1] = "DomeRingEmitter1"; + }; + +datablock TracerProjectileData(BaseProjectile) { + className = "TracerProjectileData"; + Explosion = "BaseExplosion"; + dryVelocity = "0.1"; + wetVelocity = "0.1"; + fizzleTimeMS = "32"; + lifetimeMS = "32"; + explodeOnDeath = "1"; + crossSize = "0.1"; + renderCross = "0"; + isFXUnit = "1"; + }; + +datablock TracerProjectileData(DomeProjectile):BaseProjectile + { + Explosion = "DomeExplosion"; + }; + +datablock TracerProjectileData(DomeRingProjectile):BaseProjectile + { + Explosion = "DomeRingExplosion"; + }; + +datablock TracerProjectileData(HugeShProjectile):BaseProjectile + { + Explosion = "HugeShExplosion"; + }; + +datablock TracerProjectileData(InitialProjectile):BaseProjectile + { + Explosion = "InitialExplosion"; + }; + + +function shockwave(%pos,%nrm,%dat) +{ +if (%dat $= "") + %dat = BaseProjectile; + + %p1 = new TracerProjectile() + { + dataBlock = %dat; + initialDirection = %nrm; + initialPosition = %pos; + }; +} + +function whiteout(%pos,%minrad,%maxrad) +{ + + InitContainerRadiusSearch(%pos,%maxrad, $TypeMasks::PlayerObjectType | + $TypeMasks::TurretObjectType); + + while ((%damage = containerSearchNext()) != 0) + { + %dist = containerSearchCurrDist(); + + %eyeXF = %damage.getEyeTransform(); + %epX = firstword(%eyeXF); + %epY = getWord(%eyeXF, 1); + %epZ = getWord(%eyeXF, 2); + %eyePos = %epX @ " " @ %epY @ " " @ %epZ; + %eyeVec = %damage.getEyeVector(); + + // Make sure we can see the thing... + if (ContainerRayCast(%eyePos, %pos, $TypeMasks::TerrainObjectType | + $TypeMasks::InteriorObjectType | + $TypeMasks::StaticObjectType, %damage) !$= "0") + { + continue; + } + + + + %distFactor = (%maxrad-%dist)/(%maxrad-%minrad); + %dif = VectorNormalize(VectorSub(%pos, %eyePos)); + %dot = VectorDot(%eyeVec, %dif); + + %difAcos = mRadToDeg(mAcos(%dot)); + %dotFactor = 1.0; + if (%difAcos > 60) + %dotFactor = ((1.0 - ((%difAcos - 60.0) / 120.0)) * 0.2) + 0.3; + else if (%difAcos > 45) + %dotFactor = ((1.0 - ((%difAcos - 45.0) / 15.0)) * 0.5) + 0.5; + + %totalFactor = %dotFactor * %distFactor; + + %prevWhiteOut = %damage.getWhiteOut(); + + + %whiteoutVal = %prevWhiteOut + %totalFactor; + if(%whiteoutVal > 1) + { + //error("whitout at max"); + %whiteoutVal = 1; + } + + %damage.setWhiteOut( %whiteoutVal ); + } +} + + +function TracerProjectile::ShockwaveDamage(%pos,%size,%lastsize) +{ +InitContainerRadiusSearch(%pos, %area, $TypeMasks::VehicleObjectType | $TypeMasks::PlayerObjectType |$TypeMasks::StaticShapeObjectType| $TypeMasks::ItemObjectType | $TypeMasks::CorpseObjectType); // ); + + %numTargets = 0; + while ((%targetObject = containerSearchNext()) != 0) + { + %dist = containerSearchCurrRadDamageDist(); + %distPct = %dist / %area; + + %coverage = calcExplosionCoverage(%pos, %targetObject, + ($TypeMasks::InteriorObjectType | + $TypeMasks::TerrainObjectType | + $TypeMasks::ForceFieldObjectType)); + if (%coverage == 0) + continue; + + if (%area < 500) + %power = %area; + else + %power = Limit(500 - %area,0,200); + + if (%dist > %lastar) //Shockwave + { + %force = (%power/100)*%targetobject.getDatablock().mass; + %damage = Limit(100/%dist,0,100); + %upvec = "0 0 1"; + } + else + { + %force = 0; + %damage = Limit(5/%dist,0,100); + %upvec = ""; + } + + %tgtPos = %targetObject.getWorldBoxCenter(); + %vec = VectorNormalize(VectorAdd(vectorNeg(vectorNormalize(vectorSub(%pos, %tgtPos))),%upvec)); + %nForce = %force * %distPct * 10; + %forceVector = vectorScale(%vec, %nForce); + + if(!%targetObject.inertialDampener && !%targetObject.getDatablock().forceSensitive) + %targetObject.applyImpulse(pos( %targetObject), %forceVector); + if (%damage>0.01) + %targetObject.getDataBlock().damageObject( %targetObject, 0,pos( %targetObject),%damage,$DamageType::Explosion); + } +} + + +function PlasmaBolt::onExplode(%data, %proj, %pos, %mod) +{ +//funkycurve("0 0 110",%pos); +mpm_calc("0 0 110",%pos,1,0,0); +} + + +//Dfunctions + + +function VectorDivide(%vec1,%vec2) +{ +%x1 = getWord(%vec1,0); +%y1 = getWord(%vec1,1); +%z1 = getWord(%vec1,2); +%x2 = getWord(%vec2,0); +%y2 = getWord(%vec2,1); +%z2 = getWord(%vec2,2); +%x3 = 0; +%y3 = 0; +%z3 = 0; +if (%x1 != 0||%x2 != 0) + %x3 = %x1/%x2; +if (%y1 != 0||%y2 != 0) + %y3 = %y1/%y2; +if (%z1 != 0||%z2 != 0) + %z3 = %z1/%z2; +return %x3 SPC %y3 SPC %z3; +} + +function VirpassVector(%obj,%vec) +{ +%virvec = floorvec(VectorNormalize(VirVec(%obj,%vec)),1000); +%mask = floorvec(VectorMultiply(VectorScale(VectorNormalize(%virvec),1/mPow(2,0.5)),%obj.getRealSize()),1000); +%inoutvec = VectorMultiply( VectorNormalize( TopVec( VAbs( VectorDivide( %virvec,%mask ) ))),%obj.getRealSize()); +%pass = VectorScale( %virvec,VectorLen( VectorDivide( %inoutvec,%virvec ) ) ); +return %pass; +} + +function getpassVector(%obj,%vec) +{ +return RealVec(%obj,VirpassVector(%obj,%vec)); +} + +function getpassLength(%obj,%vec) +{ +return VectorLen(getpassVector(%obj,%vec)); +} diff --git a/scripts/MPM/MPM_Launch.cs b/scripts/MPM/MPM_Launch.cs new file mode 100644 index 0000000..24f6fd1 --- /dev/null +++ b/scripts/MPM/MPM_Launch.cs @@ -0,0 +1,185 @@ +datablock AudioProfile(FwProjectileSound) +{ + filename = "armor/thrust_UW.wav"; + description = ProjectileLooping3d; + preload = true; +}; + +datablock ItemData(MpmLaucher) +{ + className = Pack; + catagory = "Funky"; + shapeFile = "Turret_Muzzlepoint.dts"; + mass = 1; + elasticity = 0.0; + friction = 1.0; + computeCRC = true; +}; + +datablock TurretImageData(MpmLauchPoint) +{ +shapeFile = "Turret_Muzzlepoint.dts"; +item = PlasmaBarrelLargePack; +offset = "0 0 0"; +rotation = "0 1 0 90"; +}; + +///old algo +//%time = Limit(VectorLen(%dist)/20,30,360); +//%z = getWord(%dist,2); +//%x = GetWord(%dist,0) SPC GetWord(%dist,1); +//%x = Mpow(VectorDot(%x,%x),0.5); +//%co1 = mpow(4*(mpow(%x,2))+ mpow(2*%muz*%time+%ac*mpow(%time,2)+2*%z,2),0.5); +//%co2 = %time * (2*%muz * %time+%ac*mpow(%time,2)+2*%z); +//%vector = (%x*%co1)/(%co2) SPC (%co1/(2*%time)); +//%vector = VectorAdd(VectorScale(VectorNormalize(GetWords(%dist,0,1)),getWord(%vector,0)) ,"0 0" SPC getWord(%vector,1)); +//%p=launchmpm(%start,"0 0 -1",%vector,%time*1000+5000); + + +//Algo for mpm_missile lauch. +//-Stage1- +//Lauch up a certain amount of time +//-Stage2- +//Turn missile and head for target + +function mpm_calc(%start,%end,%up,%dat) +{ +if (!IsObject(%dat)) + %dat = MpmMissile1; +if (%up $= "") + %up = "0 0 1"; + +%ac = %dat.acceleration; //Acceleration for calc + +%vector = VectorSub(%end,%start); //Vector source,target +%dir = VectorNormalize(%vector); + +if (mAbs(VectorDot(%up,%dir))==1) //can't fire directly up or down. + return -1; +%rup = VectorNormalize(VectorCross(%up,%dir)); +%up = VectorNormalize(%up); +%ndir = VectorNormalize(VectorCross(VectorCross(%up,%dir),%up)); + +%z = VectorDot(%up,%dir)*VectorLen(%vector); +%x = VectorDot(%ndir,%dir)*VectorLen(%vector); + +%mintime = mSqrt(2*%x)/mSqrt(%ac); //Minium travel time +%time = %mintime + 5; //Added 5 seconds for slack + +//Calculations for preffered arc. + %root = mSqrt(Mpow(%ac,2)*Mpow(%time,4)-4*Mpow(%x,2)); + + %ltimeco1 = %ac*Mpow(%time,2)+4*%root+8*%z; + %ltimeco2 = -4*Mpow(%x,2)+%ac*Mpow(%time,2)*%ltimeco1; + %ltimeco3 = 2*%ac*%time; + %ltime = (-1*%root+mSqrt(%ltimeco2))/%ltimeco3; + + %a = (%ac*%ltime) /2; + %loc = %a*%ltime; + + %co = %ac*mPow(%time,2); + + %xx = 2*%x/%co; + %zz = -1*(%root/%co); + +%vz = VectorScale(%up,%zz); +%vx = VectorScale(%ndir,%xx); + +%vector = VectorAdd(%vx,%vz); + +return %ltime SPC %time SPC %loc SPC %vector SPC %a; +} + + + +function Launch_Mpm(%pos,%dir,%speed,%time,%data) +{ +%dir = VectorNormalize(%dir); + + %obj = new Item() + { + className = Item; + dataBlock = MpmLaucher; + }; + %obj.mountimage(MpmLauchPoint,0); + %obj.setTransform(%pos); + %obj.setVelocity(%speed); + %p = %obj.Fire_MpM(%dir,%data); + %obj.schedule(50,"delete"); + +%p.lasterror = "0 0 0"; +%p.lasttime = GetSimTime(); +if (%time !$= "") + %p.dietime = GetSimTime()+%time; + %p.schedule(%time,"delete"); + +%p.addToMPMGroup(); +return %p; +} + +function ProjectileData::Create(%data,%pos,%dir,%speed) +{ +%obj = new Item() + { + className = Item; + dataBlock = MpmLaucher; + }; + %obj.mountimage(MpmLauchPoint,0); + %obj.setTransform(%pos); + if (VectorLen(%speed) > 200) + %speed = VectorScale(VectorNormalize(%speed),200); + %obj.setVelocity(%speed); + %p = %obj.Fire_MpM(%dir,%data); + %obj.schedule(50,"delete"); +return %p; +} + +function GameBase::Fire_MpM(%obj,%dir,%data) +{ +%speed = %obj.getVelocity(); +%classname = %data.classname; +%class = getSubStr(%classname,0,strLen(%classname)-4); +%p = new (%class)() + { + datablock = %data; + initialDirection = %dir; + initialPosition = %obj.getWorldBoxCenter(); + SourceObject = %obj; + SourceSlot = 0; + }; +%p.StartVelocity = %speed; +%p.createtime=getSimTime(); + +return %p; +} + +function extend(%p,%odir) +{ +%dir = %p.InitialDirection; +%pos = VectorAdd(%p.InitialPosition,VectorScale(%dir,-0.5)); +%left = VectorNormalize(VectorCross(VectorNormalize(%odir),"0 0 1")); +%p1 = new SeekerProjectile() + { + dataBlock = mpmmissile2; + initialDirection = %dir; + initialPosition = VectorAdd(%pos,VectorScale(%left,5)); + sourceObject = %p.sourceObject; + }; + +%p2 = new SeekerProjectile() + { + dataBlock = mpmmissile2; + initialDirection = %dir; + initialPosition = VectorAdd(%pos,VectorScale(%left,-5)); + sourceObject = %p.sourceObject; + }; +%p1.createtime=getSimTime(); + %p1.StartVelocity = %p.sourceObject.GetVelocity(); +%p2.createtime=getSimTime(); + %p2.StartVelocity = %p.sourceObject.GetVelocity(); +%dietime = %p.dietime-GetSimTime(); +%p1.schedule(%dietime+10000,"delete"); +%p2.schedule(%dietime+10000,"delete"); +} + + diff --git a/scripts/MPM/MPM_base.cs b/scripts/MPM/MPM_base.cs new file mode 100644 index 0000000..eb69266 --- /dev/null +++ b/scripts/MPM/MPM_base.cs @@ -0,0 +1,2320 @@ +//Give your avarage mpb unless enabled.. :) +$mpm::nukempb = 1; //Mpb's deploy with nukes +$mpm::targetenemies = 0; //Enemy targets/lasers can be targeted +$mpm::targetmpbs = 1; //Mpbs become a target when deployed. + + + +$mpm_loads = 0; +$mpm_ae=0; +$mpm_ve=0; +$mpm_te=0; +$mpm_be=0; +$mpm_ne=0; + +//Discourage damage payloads by putting them at end of list. >:D +exec("scripts/mpm/MpM_Ae.cs"); +exec("scripts/mpm/MpM_Se.cs"); //Missile datablocks +exec("scripts/mpm/MpM_Te.cs"); //Telleporter Missile +exec("scripts/mpm/MpM_Ve.cs"); //Vehicle missile +exec("scripts/mpm/MpM_Be.cs"); //Multi payload missiles +if ($mpm_NE != 1) + { + $mpm_load[$mpm_loads] = Mpm_Nuke_Load; + $mpm_loads++; + $mpm_load[$mpm_loads] = Mpm_Nuke2_Load; + $mpm_loads++; + $mpm_load[$mpm_loads] = Mpm_Hole_Load; + $mpm_loads++; + $mpm_ne = 1; + } + + +//All missiles loaded so, +//Don't complain it seems to work perfectly :D +MpmMissile1.LifeTimeMs = -1; +Mpm_B_MIS.LifeTimeMs = -1; +Mpm_B_MIS1.LifeTimeMs = -1; +Mpm_B_MIS2.LifeTimeMs = -1; +Mpm_B_MIS3.LifeTimeMs = -1; +Mpm_B_MIS4.LifeTimeMs = -1; + +datablock ItemData(Mpm_Nuke_Load):Mpm_Base_Load +{ + cost = 150; + name = "[Weapon] Drain Bramage's, Attomic(tm) Nuke Cannon"; + missile = MpmMissile1; + slot = 0; +}; + +datablock ItemData(Mpm_Nuke2_Load):Mpm_Base_Load +{ + cost = 250; + name = "[Weapon] Arrow IV 150 kt Nuke"; + missile = MpmMissile1; + slot = 0; +}; + +datablock ItemData(Mpm_Hole_Load):Mpm_Base_Load +{ + cost = 200; + name = "[Weapon] Black Hole"; + missile = MpmMissile1; + slot = 0; +}; + +datablock AudioProfile(LaserTargetSound) { + fileName = "fx/misc/red_alert_short.wav"; + description = AudioClose3d; + preload = true; + effect = MotionSensorDeployEffect; +}; + +datablock TurretData(MpmTurret) : TurretDamageProfile +{ + className = TurretBase; + catagory = "Turrets"; + shapeFile = "turret_base_large.dts"; + preload = true; + + mass = 1.0; // Not really relevant + + maxDamage = 2.25; + destroyedLevel = 2.25; + disabledLevel = 1.35; + explosion = TurretExplosion; + expDmgRadius = 15.0; + expDamage = 0.66; + expImpulse = 2000.0; + repairRate = 0.5; + emap = true; + + thetaMin = 90; + thetaMax = 90; + + isShielded = true; + energyPerDamagePoint = 50; + maxEnergy = 150; + rechargeRate = 0.31; + humSound = SensorHumSound; + pausePowerThread = true; + + targetNameTag = 'Base'; + targetTypeTag = 'Turret'; + sensorData = TurretBaseSensorObj; + sensorRadius = TurretBaseSensorObj.detectRadius; + sensorColor = "0 212 45"; + heatSignature = 1.0; +}; + + +datablock TurretImageData(MpmBarrel) +{ + shapeFile = "Turret_Muzzlepoint.dts"; + item = PlasmaBarrelLargePack; + + projectile = PlasmaBarrelBolt; + projectileType = LinearFlareProjectile; + usesEnergy = true; + fireEnergy = 1; + minEnergy = 1; + emap = true; + + offset = "-0.7 -0.04 -0.4"; + rotation = "0 1 0 90"; + + yawVariance = 30.0; // these will smooth out the elf tracking code. + pitchVariance = 360.0; // more or less just tolerances + + + // Turret parameters + activationMS = 1000; + deactivateDelayMS = 1500; + thinkTimeMS = 200; + degPerSecTheta = 5; + degPerSecPhi = 5; + attackRadius = 10000; + + // State transitions + stateName[0] = "Activate"; + stateTransitionOnNotLoaded[0] = "Dead"; + stateTransitionOnLoaded[0] = "ActivateReady"; + + stateName[1] = "ActivateReady"; + stateSequence[1] = "Activate"; + stateSound[1] = PBLSwitchSound; + stateTimeoutValue[1] = 1; + stateTransitionOnTimeout[1] = "Ready"; + stateTransitionOnNotLoaded[1] = "Deactivate"; + stateTransitionOnNoAmmo[1] = "NoAmmo"; + + stateName[2] = "Ready"; + stateTransitionOnNotLoaded[2] = "Deactivate"; + stateTransitionOnTriggerDown[2] = "Fire"; + stateTransitionOnNoAmmo[2] = "NoAmmo"; + + stateName[3] = "Fire"; + stateTransitionOnTimeout[3] = "Reload"; + stateTimeoutValue[3] = 0.15; //0.3 + stateFire[3] = true; + stateRecoil[3] = LightRecoil; + stateAllowImageChange[3] = false; + stateSequence[3] = "Fire"; + stateScript[3] = "onFire"; + stateSound[3] = ""; + + stateName[4] = "Reload"; + stateTimeoutValue[4] = 0.4; //0.8 + stateAllowImageChange[4] = false; + stateSequence[4] = "Reload"; + stateTransitionOnTimeout[4] = "Ready"; + stateTransitionOnNotLoaded[4] = "Deactivate"; + stateTransitionOnNoAmmo[4] = "NoAmmo"; + + stateName[5] = "Deactivate"; + stateSequence[5] = "Activate"; + stateDirection[5] = false; + stateTimeoutValue[5] = 1; + stateTransitionOnLoaded[5] = "ActivateReady"; + stateTransitionOnTimeout[5] = "Dead"; + + stateName[6] = "Dead"; + stateTransitionOnLoaded[6] = "ActivateReady"; + + stateName[7] = "NoAmmo"; + stateTransitionOnAmmo[7] = "Reload"; + stateSequence[7] = "NoAmmo"; +}; + +datablock StaticShapeData(MpmTurretTarg) : StaticShapeDamageProfile + { + shapeFile = "Turret_Muzzlepoint.dts"; + className = Target; + dynamicType = $TypeMasks::SensorObjectType; + heatSignature = 1; + //targetTypeTag = 'mtc'; + sensorData = DeployedOutdoorTurretSensor; + maxDamage = 1000; + destroyedLevel = 200.20; + disabledLevel = 200.00; + }; + +datablock StaticShapeData(VisTarget) : StaticShapeDamageProfile + { + className = "target"; + shapeFile = "reticle_bomber.dts"; + }; + +datablock StaticShapeData(TurretArm) : StaticShapeDamageProfile + { + className = "crate"; + shapeFile = "turret_base_large.dts";//"vehicle_air_hapc.dts"; +}; + +datablock StaticShapeData(TurretLift) : StaticShapeDamageProfile + { + className = "crate"; + shapeFile = "turret_base_mpb.dts";//"vehicle_air_hapc.dts"; +}; + +datablock StaticShapeData(SelectionPad) : StaticShapeDamageProfile + { + className = "crate"; + shapeFile = "station_inv_mpb.dts";//"vehicle_air_hapc.dts"; +}; + +datablock TriggerData(nukepadTrigger) +{ + tickPeriodMS = 500; +}; + +function SelectionPad::onDestroyed(%this, %obj, %prevState) +{ +%obj.remTrigger(); +Parent::onDestroyed(%this, %obj, %prevState); +%obj.schedule(500, "delete"); +} + +datablock ShapeBaseImageData(Supportl) { + + shapeFile = "stackable2L.dts"; + mountPoint = 3; + offset = "1.7 1.5 -2"; + rotation = "1 0 0 90"; + +}; + +datablock ShapeBaseImageData(Supportr) { + + shapeFile = "stackable2L.dts"; + mountPoint = 2; + offset = "-1.7 1.5 -2"; + rotation = "1 0 0 90"; + +}; + +datablock ShapeBaseImageData(SupportM1) { + + shapeFile = "stackable2L.dts"; + mountPoint = 3; + offset = "0 -2.8 0"; + rotation = "1 0 0 90"; + +}; + +datablock ShapeBaseImageData(SupportM2) { + + shapeFile = "stackable2L.dts"; + mountPoint = 3; + offset = "0 -4.8 0"; + rotation = "1 0 0 90"; + +}; + +datablock StaticShapeData(Baseb) : StaticShapeDamageProfile + { + className = "crate"; + shapeFile = "stackable2L.dts";//"vehicle_air_hapc.dts"; + }; + +datablock StaticShapeData(FrameS) : StaticShapeDamageProfile + { + className = "crate"; + shapeFile = "vehicle_air_scout.dts";//"vehicle_air_hapc.dts"; + }; + + + +datablock StaticShapeData(CBarrel) : StaticShapeDamageProfile + { + className = "crate"; + shapeFile = "weapon_mortar.dts";//"vehicle_air_hapc.dts"; + + +}; + +datablock StaticShapeData(MImage) : StaticShapeDamageProfile + { + className = "crate"; + shapeFile = "bomb.dts";//"vehicle_air_hapc.dts"; + + +}; + + + +datablock StaticShapeData(Frame) : StaticShapeDamageProfile + { + className = "crate"; + shapeFile = "Vehicle_air_hapc.dts";//"vehicle_air_hapc.dts"; + +}; + + +datablock StaticShapeData(BoosterM) : StaticShapeDamageProfile + { + className = "crate"; + shapeFile = "Weapon_missile_projectile.dts";//"vehicle_air_hapc.dts"; + + +}; + + +datablock TurretData(BaseArmTurret) : TurretBaseLarge +{ + className = TurretBase; + catagory = "Turrets"; + shapeFile = "turret_base_large.dts"; + preload = true; + + mass = 1.0; // Not really relevant + + maxDamage = 2.25; + destroyedLevel = 2.25; + disabledLevel = 1.35; + explosion = TurretExplosion; + expDmgRadius = 15.0; + expDamage = 0.66; + expImpulse = 2000.0; + repairRate = 0.5; + emap = true; + + thetaMin = 0; + thetaMax = 180; + + isShielded = true; + energyPerDamagePoint = 50; + maxEnergy = 150; + rechargeRate = 0.31; + humSound = SensorHumSound; + pausePowerThread = true; + + canControl = true; + cmdCategory = "Tactical"; + cmdIcon = CMDTurretIcon; + cmdMiniIconName = "commander/MiniIcons/com_turretbase_grey"; + targetNameTag = 'Base'; + targetTypeTag = 'Turret'; + sensorData = TurretBaseSensorObj; + sensorRadius = TurretBaseSensorObj.detectRadius; + sensorColor = "0 212 45"; + heatSignature = 1.0; + firstPersonOnly = true; + + debrisShapeName = "debris_generic.dts"; + debris = TurretDebris; +}; + +function GameBase::MakeTurret(%obj,%loc) +{ +//TURRET +%turret = new Turret() + { + className = DeployedTurret; + dataBlock = MpmTurret; + maxdamage = 20; + }; +%turret.SetTransform(%loc); +%turret.setSelfPowered(); +%turret.mountImage("MpmBarrel",0,false); +%turret.team = %obj.team; +setTargetSensorGroup(%turret.getTarget(), %obj.team); +%turret.startfade(0,0,1); +//SIGN +%sign = new StaticShape(){ +dataBlock = MpmTurretTarg; +}; +%sign.team = 3; +%sign.setHeat(1); +%obj.mountObject(%sign, 4); +//setTargetSensorGroup(%sign.getTarget(),3); +%obj.signature = %sign; +%sign.owner = %obj; + +%turret.aimtarget = %sign; + +%turret.mpm_barrel_on(); +} + +function MpmTurret::onRemove(%this, %obj) +{ +%obj.mpm_all_off(1); +Parent::onRemove(%this, %obj); +} + +function GameBase::Mpm_Turret(%obj) +{ +%turret = new Turret() + { + className = DeployedTurret; + dataBlock = MpmTurret; + maxdamage = 20; + }; +%turret.SetTransform(VectorAdd(%obj.getTransform(),realvec(%obj,"0 1.5 -0.5")) SPC %obj.getRotation()); +//%obj.MountObject(%turret,5); +%turret.setSelfPowered(); +%turret.mountImage("MpmBarrel",0,false); +%turret.team = %obj.team; +%turret.mpb = %obj; +setTargetSensorGroup(%turret.getTarget(), %obj.team); +%turret.mpm_all_on(); +%turret.playThread(1,"activate"); +%turret.addToMPMGroup(1); +return %turret; +} + +function MpmTurret::selectTarget(%this, %turret) +{ +%turretTarg = %turret.getTarget(); + if(%turretTarg == -1) + return; +if (Isobject(%turret.aimtarget)) + { + if (!IsObject(%turret.aimtarget.source) && %turret.canfire) + { + %turret.Mpm_CycleTargets(""); + return ""; + } + %turret.setTargetObject(%turret.aimtarget); + +if (!isObject(%turret.leftpad)) + return; + + %tdir = VectorNormalize(VectorSub(%turret.aimtarget.getTransform(),%turret.getMuzzlePoint(0))); + %vec = "0 1 0"; + %rot = %turret.getSlotRotation(0); + %dir = validateVal(MatrixMulVector("0 0 0" SPC %rot ,%vec)); + %diff = VectorDot(%tdir,%dir); + + if (%diff > 0.9 && IsObject(%turret.leftpad.getMountedObject(0)) && %turret.canfire) + { + %plyr = %turret.leftpad.getMountedObject(0); + %tdir = VectorNormalize(VectorSub(%turret.aimtarget.targetloc,%plyr.getEYePoint())); + if (!Isobject(%turret.lvistarget)) + { + %vistar = new StaticShape() + { + dataBlock = VisTarget; + }; + %turret.Play3D(MobileBaseStationdeploySound); + %turret.lvistarget=%vistar; + } + %turret.lvistarget.setScale("0.01 0.01 0.01"); + %rot = fullrot(VectorScale(%tdir,-1),"0 0 1"); + + %pos = VectorAdd(%plyr.getEYePoint(),VectorScale(%tdir,0.5)); + %turret.lvistarget.setTransform(%pos SPC %rot); + } + else if (IsObject(%turret.lvistarget)) + { + %turret.lvistarget.delete(); + } + } +} + + +function Mpm_Beacon::onDestroyed(%this, %obj, %prevState) +{ +Parent::onDestroyed(%this, %obj, %prevState); +%obj.mpm_off_all(1); +%obj.schedule(1500,"delete"); +} + + +function MpmBarrel::onFire( %data, %obj, %slot ) +{ +//%obj.firempmNow(); +} + +function GameBase::FireMPMNow(%obj) +{ +%tdir = VectorNormalize(VectorSub(%obj.aimtarget.getTransform(),%obj.getMuzzlePoint(0))); +%vec = "0 1 0"; +%rot = %obj.getSlotRotation(0); +%dir = validateVal(MatrixMulVector("0 0 0" SPC %rot ,%vec)); +%diff = vectorDot(%tdir,%dir); + +if (%obj.canfire && IsObject(%obj.rightpad.getMountedObject(0)) && %diff > 0.9) + { + %data = $mpm_load[%obj.load]; + if (%data.slot == 1||%data.slot == 2) + %obj.Lauch_mpm(%data.slot); + else if (%data.slot == 3) + { + %obj.Lauch_mpm(1); + %obj.Lauch_mpm(2); + } + else if (%data.slot == 4) + { + %slot=%obj.HasLoad(4); + if (%slot == 3) + %obj.Lauch_mpm(Mfloor(GetRandom()*2+1)); + else if (%slot == 2 || %slot == 1) + %obj.Lauch_mpm(%slot); + } + else + %obj.Lauch_mpm(0); + } +} + +function GameBase::Lauch_mpm(%obj,%slot) +{ +%data = $mpm_load[%obj.load]; +%offset = realvec(%obj.barrel,"0 -2 0"); +if (%slot == 1) + %barrelt = VectorAdd(%obj.rightbarrel.getWorldBoxCenter(),%offset); +else if (%slot == 2) + %barrelt = VectorAdd(%obj.leftbarrel.getWorldBoxCenter(),%offset); +else + %barrelt = %obj.barrel.getTransform(); +%up = Realvec(%obj,"0 0 1"); + +%start = VectorAdd(%barrelt,VectorScale(%up,5)); +%end = %obj.aimtarget.targetloc; +%forward = VectorNormalize(VectorCross(VectorCross(%up,VectorSub(%end,%start)),%up)); + +if (%data.offset !$= "") + %end = VectorAdd(%end,VectorAdd(VectorScale(%forward,GetWord(%data.offset,0)),VectorScale(%up,GetWord(%data.offset,1)))); + + +%missileblock = %data.missile; + +%solution = mpm_calc(%start,%end,%up,%missileblock); +if (%solution != -1) + { +if (%obj.aimtarget.source.player.client) + { + bottomPrint( %obj.aimtarget.source.player.client, "Missile Lauched at your target by:" @ %obj.launcher.namebase, 5, 3); + %obj.aimtarget.source.firedat++; + } +%ltime = GetWord(%solution,0)*1000; +%time = GetWord(%solution,1)*1000; +%loc = GetWord(%solution,2); +%vector = GetWords(%solution,3,5); +%a = GetWord(%solution,6); +%p = Launch_Mpm(%start,%up,"0 0 0",%ltime+200,%missileblock); +%p.team = %obj.team; +%p.source = %obj; +%p.traject = %start SPC %up SPC %loc SPC %a SPC %vector SPC %time; +%p.load = %data; +%p.targetlocation = %end; +%p.owner = %obj.launcher; +%data.schedule(%ltime,"Stage2",%p); +%data.Stage1(%p); + +if (%p.owner.player.getObjectMount().base == %obj) + obsproj(%p,%p.owner); +%obj.ammo-= %data.cost; +%dist = VectorDist(%start,%end); +%obj.fuel-= mFloor(%dist/10); +if (%obj.ammo <= 0) + %obj.ammo = 1; +if (%obj.fuel <= 0) + %obj.fuel = 1; +%obj.mpm_load_off(0,%slot+1); +%obj.schedule(30000,"mpm_load_on",%slot+1); + } + +} + +function obsproj(%p,%player) +{ +%client = %player; +if ( !isObject( %client.comCam ) ) + { + %client.comCam = new Camera() + { + dataBlock = CommanderCamera; + }; + MissionCleanup.add(%client.comCam); + commandToClient(%client, 'ControlObjectResponse', true, getControlObjectType(%p,%client.player)); + messageClient(%colObj.client, 'CloseHud', "", 'inventoryScreen'); + %client.setControlObject(%client.comCam); + commandToClient(%client, 'CameraAttachResponse', true); + } + +%client.comCam.setTransform(%p.getTransform()); +%client.comCam.setOrbitMode(%p,%p.getTransform(),0,20,-20); +%client.moveprojectile = %p; + +} + + +function GameData::Armer(%base,%target) +{ +%arm = new StaticShape() + { + dataBlock = TurretArm; + }; +%arm.setScale("0.1 0.1 0.1"); +%arm.playThread(0,"activate"); +%base.mountObject(%arm,0); +return(%arm); +} + + +//turret +// 1barm +// 0base +// 0arm +// 1rbase +// 0barrel +// 0missile +// 2leftjoint +// 3rightjoint +// 1frame +// 3leftarm +// 1leftbarrel +// 0leftmissile +// 4rightarm +// 1rightbarrel +// 0rightmissile +// + +function GameBase::Mpm_Barrel_on(%obj) +{ +if (!IsObject(%obj.barrel)) + { + %arm = new StaticShape() + { + dataBlock = TurretArm; + }; + %arm.startFade(0,0,1); + %arm.playThread(1,"elevate"); + %arm.stopThread(1); + %arm.setScale("0.1 0.1 0.1"); + %obj.mountObject(%arm,0); + + %barrel = new StaticShape() + { + dataBlock = CBarrel; + }; + %barrel.startFade(0,0,1); + %arm.mountObject(%barrel,0); + %barrel.setScale("8 8 8"); + + %obj.barrel = %barrel; + %barrel.arm = %arm; + %barrel.turret = %obj; + } +%obj.barrel.startfade(1000,0,0); +} + +function GameBase::Mpm_Barrel_off(%obj,%del) +{ +%obj.remfromMpmGroup(1); +if (IsObject(%obj.barrel)) + { + if (!%del) + { + %obj.barrel.startfade(1000,0,1); + } + else if (%del) + { + %obj.barrel.schedule(1000,"delete"); + %obj.barrel.arm.schedule(1000,"delete"); + } + } + +} + +function GameBase::Mpm_Support_on(%obj) +{ +if (!IsObject(%obj.barrel.frame)) + { + if (%disabled) + { + %basearm = new StaticShape() + { + dataBlock = TurretArm; + }; + %basearm.startFade(0,0,1); + %basearm.setScale("0.1 0.1 0.1"); + %basearm.playThread(0,"activate"); + %basearm.setThreaddir(0,false); + %obj.mountObject(%basearm,1); + + + %base = new StaticShape() + { + dataBlock = baseb; + }; + %base.startFade(0,0,1); + %base.setScale("4.5 4.5 2"); + %basearm.mountObject(%base,0); + %obj.base = %base; + %base.arm = %basearm; + + %rbase = new StaticShape() + { + dataBlock = baseb; + }; + %rbase.startFade(0,0,1); + %rbase.setScale("4.5 4.5 1.9"); + %obj.barrel.arm.mountObject(%rbase,1); + %obj.rbase = %rbase; + } + + %ghost = new StaticShape() + { + dataBlock = baseb; + }; + %ghost.startFade(0,0,1); + %ghost.setScale("1.5 1.5 4"); + %obj.barrel.arm.mountObject(%ghost,1); + %obj.barrel.ghost = %ghost; + %ghost.base = %obj; + + %frame = new StaticShape() + { + dataBlock = frame; + }; + %frame.startFade(0,0,1); + %frame.setScale("0.1 0.1 0.1"); + %obj.barrel.MountObject(%frame,1); + %obj.barrel.frame = %frame; + + %leftarm = new StaticShape() + { + dataBlock = TurretArm; + }; + %leftarm.startFade(0,0,1); + %leftarm.setScale("0.1 0.1 0.1"); + %leftarm.playThread(0,"activate"); + %leftarm.setThreadDir(0,false); + %leftarm.playThread(1,"elevate"); + %frame.MountObject(%leftarm,3); + %frame.leftarm = %leftarm; + + %rightarm = new StaticShape() + { + dataBlock = TurretArm; + }; + %rightarm.startFade(0,0,1); + %rightarm.setScale("0.1 0.1 0.1"); + %rightarm.playThread(0,"activate"); + %rightarm.setThreadDir(0,false); + %rightarm.playThread(1,"elevate"); + %frame.MountObject(%rightarm,4); + %frame.rightarm = %rightarm; + + %leftpad = new StaticShape() + { + dataBlock = SelectionPad; + }; + //%leftpad.startFade(0,0,1); + %leftpad.playThread(0,"deploy"); + %leftpad.setThreaddir(0,false); + %leftpad.PlayThread(1,"Activate1"); + %leftpad.setThreadDir(1,false); + + %obj.leftpad=%leftpad; + %leftpad.base = %obj; + //%leftarm.MountObject(%leftpad,0); + %leftpad.setTransform(VectorAdd(%obj.getTransform(),realvec(%obj,"-4.5 -2.5 2.2")) SPC rotAdd(%obj.getRotation(),"0 0 1" SPC 1.56)); + %leftpad.setScale("1 1 1"); + + %rightpad = new StaticShape() + { + dataBlock = SelectionPad; + }; + //%rightpad.startFade(0,0,1); + %rightpad.playThread(0,"deploy"); + %rightpad.setThreaddir(0,false); + %obj.rightpad=%rightpad; + %rightpad.base = %obj; + %rightpad.PlayThread(1,"Activate1"); + %rightpad.setThreadDir(1,false); + //%rightarm.MountObject(%rightpad,0); + %rightpad.setTransform(VectorAdd(%obj.getTransform(),realvec(%obj,"4.5 -2.5 2.2")) SPC rotAdd(%obj.getRotation(),"0 0 -1" SPC 1.56)); + %rightpad.setScale("1 1 1"); + + %leftbarrel = new StaticShape() + { + dataBlock = CBarrel; + }; + %leftbarrel.startFade(0,0,1); + %leftbarrel.SetScale("5 4 5"); + %leftarm.MountObject(%leftbarrel,1); + %leftarm.barrel = %leftbarrel; + %obj.leftbarrel = %leftbarrel; + %leftbarrel.arm = %leftarm; + + %rightbarrel = new StaticShape() + { + dataBlock = CBarrel; + }; + %rightbarrel.startFade(0,0,1); + %rightbarrel.SetScale("5 4 5"); + %rightarm.MountObject(%rightbarrel,1); + %rightarm.barrel = %rightbarrel; + %obj.rightbarrel = %rightbarrel; + %rightbarrel.arm = %rightarm; + } + +//%obj.base.startfade(1000,0,0); +//%obj.rbase.startfade(1000,0,0); +%obj.rightbarrel.startfade(1000,0,0); +%obj.leftbarrel.startfade(1000,0,0); +%obj.rightpad.setThreaddir(0,true); +%obj.leftpad.setThreaddir(0,true); +%obj.rightpad.addtrigger(); +%obj.leftpad.addtrigger(); +%obj.leftbarrel.arm.setThreadDir(0,true); +%obj.rightbarrel.arm.setThreadDir(0,true); +//%obj.base.arm.setThreaddir(0,true); +%obj.barrel.mountImage("Supportr",2,true); +%obj.barrel.mountImage("Supportl",3,true); +%obj.rightbarrel.mountImage("SupportM1",2,true); +%obj.rightbarrel.mountImage("SupportM2",3,true); +%obj.leftbarrel.mountImage("SupportM1",2,true); +%obj.leftbarrel.mountImage("SupportM2",3,true); +MPM_AddLoadArms(%obj); +} + +function GameBase::Mpm_Support_off(%obj,%del) +{ + +if (IsObject(%obj.barrel.frame)) + { + MPM_RemLoadArms(%obj,%del); + if (isObject(%obj.rightpad)) + %obj.rightpad.remtrigger(); + if (isObject(%obj.leftpad)) + %obj.leftpad.remtrigger(); + if (!%del) + { + //%obj.base.startfade(1000,0,1); + //%obj.rbase.startfade(1000,0,1); + %obj.rightbarrel.startfade(1000,0,1); + %obj.leftbarrel.startfade(1000,0,1); + %obj.rightpad.setThreaddir(0,false); + %obj.leftpad.setThreaddir(0,false); + %obj.rightpad.setThreaddir(1,false); + %obj.leftpad.setThreaddir(1,false); + if (%obj.leftpad.getMountNodeObject(%i)) { + %passenger = %obj.leftpad.getMountNodeObject(%i); + %passenger.unmount(); + } + if (%obj.rightpad.getMountNodeObject(%i)) { + %passenger = %obj.rightpad.getMountNodeObject(%i); + %passenger.unmount(); + } + + + %obj.leftbarrel.arm.setThreadDir(0,false); + %obj.rightbarrel.arm.setThreadDir(0,false); + + %obj.barrel.unmountImage(2); + %obj.barrel.unmountImage(3); + %obj.rightbarrel.unmountImage(2); + %obj.rightbarrel.unmountImage(3); + %obj.leftbarrel.unmountImage(2); + %obj.leftbarrel.unmountImage(3); + } + else if (%del) + { + //%obj.base.schedule(1000,"delete"); + //%obj.base.arm.schedule(1000,"delete"); + //%obj.rbase.schedule(1000,"delete"); + %obj.barrel.frame.schedule(1000,"delete"); + %obj.barrel.frame.leftarm.schedule(1000,"delete"); + %obj.barrel.frame.rightarm.schedule(1000,"delete"); + %obj.leftpad.schedule(1000,"delete"); + %obj.rightpad.schedule(1000,"delete"); + %obj.leftpad.remtrigger(); + %obj.rightpad.remtrigger(); + %obj.leftbarrel.schedule(1000,"delete"); + %obj.rightbarrel.schedule(1000,"delete"); + %obj.barrel.ghost.schedule(1000,"delete"); + } + } +} + +//Litle console spam remover. +function SelectionPad::hasDismountOverrides(%data, %obj) +{ + return false; +} + + +function GameBase::Addtrigger(%obj) +{ +if (!IsObject(%obj.trigger)) + { + %trigger = new Trigger() + { + dataBlock = nukepadTrigger; + polyhedron = "-0.75 0.75 0.1 1.5 0.0 0.0 0.0 -1.5 0.0 0.0 0.0 2.3"; + }; + MissionCleanup.add(%trigger); + %trigger.setTransform(%obj.getTransform()); + + %trigger.pad= %obj; + %trigger.mainObj = %obj; + %trigger.disableObj = %obj; + %obj.trigger = %trigger; + } +} + +function GameBase::RemTrigger(%obj) +{ +if (IsObject(%obj.trigger)) + %obj.trigger.delete(); +} + +function GameBase::Mpm_Load_on(%obj,%slot) +{ +if (!IsObject(%obj.barrel.missile)) + { + + %missile = new StaticShape() + { + dataBlock = MImage; + }; + %missile.startFade(0,0,1); + %missile.setScale("4 8 4"); + %obj.barrel.MountObject(%missile,0); + %obj.barrel.missile=%missile; + + + %leftmissile = new StaticShape() + { + dataBlock = BoosterM; + }; + %leftmissile.startFade(0,0,1); + %leftmissile.setScale("10 23 10"); + %obj.leftbarrel.MountObject(%leftmissile,0); + %obj.leftbarrel.missile=%leftmissile; + + %rightmissile = new StaticShape() + { + dataBlock = BoosterM; + }; + %rightmissile.startFade(0,0,1); + %rightmissile.setScale("10 23 10"); + %obj.rightbarrel.MountObject(%rightmissile,0); + %obj.rightbarrel.missile=%rightmissile; + + } +if (%slot == 1 || %slot == 0) + { + %obj.barrel.missile.setScale("4 8 4"); + %obj.barrel.missile.startfade(1000,0,0); + } +if (%slot == 2 || %slot == 0) + { + %obj.rightbarrel.missile.startfade(1000,0,0); + %obj.rightbarrel.missile.setScale("10 23 10"); + } +if (%slot == 3 || %slot == 0) + { + %obj.leftbarrel.missile.startfade(1000,0,0); + %obj.leftbarrel.missile.setScale("10 23 10"); + } +if (%slot != 0) + %obj.missile[%slot-1] = 1; +else + { + %obj.missile[0] = 1; + %obj.missile[1] = 1; + %obj.missile[2] = 1; + } +} + +function GameBase::Mpm_Load_off(%obj,%del,%slot) +{ +if (IsObject(%obj.barrel.missile)) + { + if (%slot == 1 || %slot == 0) + { + %obj.barrel.missile.startfade(0,0,1); + %obj.barrel.missile.setScale("1 1 1"); + } + if (%slot == 2 || %slot == 0) + { + %obj.rightbarrel.missile.startfade(0,0,1); + %obj.rightbarrel.missile.setScale("1 1 1"); + } + if (%slot == 3 || %slot == 0) + { + %obj.leftbarrel.missile.startfade(0,0,1); + %obj.leftbarrel.missile.setScale("1 1 1"); + } + if (%del) + { + %obj.barrel.missile.schedule(1000,"delete"); + %obj.rightbarrel.missile.schedule(1000,"delete"); + %obj.leftbarrel.missile.schedule(1000,"delete"); + } + } +if (%slot != 0) + %obj.missile[%slot-1] = 0; +else + { + %obj.missile[0] = 0; + %obj.missile[1] = 0; + %obj.missile[2] = 0; + } +} + +function GameBase::HasLoad(%obj,%slot) +{ +if (%slot < 3) + return (%obj.missile[%slot]==1); +else if (%slot == 3) + return (%obj.missile[1]==1 && %obj.missile[2]==1); +else if (%slot == 4) + return (%obj.missile[1]==1) +(%obj.missile[2]==1)*2; +} + +function GameBase::Mpm_All_on(%obj) +{ +%obj.mpm_barrel_on(); +%obj.mpm_support_on(); +%obj.mpm_load_on(); +} + +function GameBase::Mpm_All_off(%obj,%del) +{ +%obj.mpm_barrel_off(%del); +%obj.mpm_support_off(%del); +%obj.mpm_load_off(%del); +if (isObject(%obj.aimtarget)) + %obj.aimtarget.delete(); +if (isObject(%obj.lvistarge)) + %obj.lvistarget.delete(); +} + + + + +function nukepadTrigger::onEnterTrigger(%data, %obj, %colObj) +{ +%pad = %obj.pad; +SelectionPadmount(%pad,%colObj); +} + +function nukepadTrigger::onLeaveTrigger(%data, %obj, %colObj) +{ +} + +function nukepadTrigger::stationTriggered(%data, %obj, %isTriggered) +{ +} +function nukepadTrigger::onTickTrigger(%data, %obj) +{ +} + + + +function SelectionPadmount(%obj,%col) +{ +if (%col.getClassName() !$= "Player" || %obj.base.team != %col.team|| IsObject(%obj.getMountedObject(0))) + return; + +%base = %obj.base; +%obj.mountObject(%col,0); +%obj.mVehicle=%col; +%obj.setThreadDir(1,true); + +//if (%col.getMountedImage(2) && %col.getMountedImage(2).getName() $= TurretMpm_Anti_DeployableImage) + //{ + //%obj.base.ammo+= 20; + //%col.getMountedImage(2).used = 0; + //%col.decInventory(TurretMpm_Anti_Deployable, 1); + //%col.UnMountImage(2); + //} + +if (%base.leftpad == %obj) + { + bottomPrint( %col.client, "Welcome to the targetting pad\n Use pack/Healthkid key to cycle targets / active scan target.\n Targets are made by deploying 3 beacons out of the pack you just got.", 10, 3); + //if (%col.getMountedImage(2).getName() != MPM_BeaconPackImage) + //{ + %col.setInventory(MPM_BeaconPack,1); + %col.getMountedImage(2).used = 0; + //} + } +if (%base.rightpad == %obj) + { + bottomPrint( %col.client, "Welcome to the launch pad\n Use pack/Healthkid key to lauch / cycle payload.\n Missle cost can be paid by wearing an anti-missile turret on this pad.", 10, 3); + } +} + +function PressButton(%obj,%player,%pad,%button) +{ +%base = %obj.base; +%list = GetMPMTargetList(%base.team,%base.getTransform(),100,5000); +if (!%base.ammo) + %base.ammo = 50; +if (!%base.fuel) + %base.fuel = 20; +if (%pad == 0) + { + if (%button == 0) + %base.Mpm_CycleTargets(%list,1); + else if (%button == 1) + { + if(%base.canfire != 1) + { + bottomPrint( %player.client, '\c2 [WARNING] \c0 cannot scan because no target is selected.\n Select a target', 10, 2); + } + else + { + obspulse(%base.aimtarget.targetloc,%player.client,5000); + pulse(%base.aimtarget.targetloc); + Mpm_report_scan(%player,%base.aimtarget.targetloc); + %reported = 1; + } + } + if (!%reported) + %base.Mpm_report_targets(%player,%list); + } +else if (%pad == 1) + { + if (%button == 0) + { + %dist = isObject(%obj.target) ? VectorDist(%obj.target.targetloc,%obj.getTransform()) : 0; + if (%base.ammo < $mpm_load[%base.load].cost) + { + bottomPrint( %player.client, "\c2 [WARNING] \c0 cannot fire because the current payload needs more ammo.\n Bring an MPM-Ammo pack (from pack dispenser) to one of the load arms\n to get more ammo.[Needs:" SPC $mpm_load[%base.load].cost SPC "Current:" SPC %base.ammo@"]", 10, 3); + } + else if(%base.fuel < mFloor(%dist/10)) + { + bottomPrint( %player.client, "\c2 [WARNING] \c0 cannot fire because the current distance requires more fuel.\n Bring an MPM-Fuel pack (from pack dispenser) to one of the load arms\n to get more ammo.[Needs:" SPC mFloor(%dist/10) SPC "Current:" SPC %base.fuel@"]", 10, 3); + } + else if(%base.canfire != 1) + { + bottomPrint( %player.client, "\c2 [WARNING] \c0 cannot fire because no target is selected.\n Select a target on the left pad.", 10, 2); + } + else if(IsObject($mpm_load[%base.load].vehicle) && !vehicleCheck($mpm_load[%base.load].vehicle, %base.team)) + { + bottomPrint( %player.client, "\c2 [WARNING] \c0 cannot fire because Spawned Vehicle will exceed maximum.", 10, 1); + } + else if(!%base.HasLoad($mpm_load[%base.load].slot)) + { + bottomPrint( %player.client, "\c2 [WARNING] \c0 cannot fire because the current missile barrel is reloading.", 10, 1); + } + else + { + %base.launcher = %player.client; + %base.firempmNow(); + } + } + else if (%button == 1) + { + %base.Mpm_CycleLoad(); + %base.Mpm_report_targets(%player,%list); + } + } +} + +function GameBase::Mpm_CycleTargets(%obj,%list,%mod) +{ +%obj.targetselection+=%mod; +if (%list $= "") + { + %obj.set_mpm_target(); + %obj.targetselection = 0; + } +else + { + %count = getWordCount(%list); + if (%obj.targetselection > %count) + { + %obj.targetselection = 0; + %obj.set_mpm_target(); + } + else if (%obj.targetselection < 0) + { + %obj.targetselection = %count; + %target = getWord(%list,%obj.targetselection-1); + %dist = VectorDist(%target.targetloc,%obj.getTransform()); + %obj.set_mpm_target(%target); + } + else + { + %target = getWord(%list,%obj.targetselection-1); + %obj.set_mpm_target(%target); + } + } + +} + +function GameBase::Mpm_CycleLoad(%obj) +{ +%obj.load++; +if (%obj.load >= $mpm_loads || %obj.load < 0) + %obj.load=0; +} + +function GameBase::Mpm_report_targets(%obj,%plyr,%list) +{ +%selection=%obj.targetselection; +if (%obj.load $= "") + %obj.load = 0; +%load = %obj.load; +%count = getWordCount(%list); +%dist = VectorDist(%obj.aimtarget.targetloc,%obj.getTransform()); +%loadname = $mpm_load[%load].name; +%loadcost = $mpm_load[%load].cost; +if (%dist > 1000) + %distname = "(distance:" @ mFloor(%dist/100)/10 @ "km)"; +else + %distname = "(distance:" @ mFloor(%dist/10)*10 @ "m)"; + +if (isObject(%obj.aimtarget.source.player.client)) + %selectionn = %selection SPC "(" @ %obj.aimtarget.source.player.client.nameBase @ "\'s Laser)"; +else if (isObject(%obj.aimtarget.source) && %obj.aimtarget.source.getDatablock().getName() $= "MpmTurret") + { + if (%obj.aimtarget.source.mpb.team != %plyr.team) + %selectionn = %selection SPC "(Enemy MPB)"; + else + %selectionn = %selection SPC "(Friendly MPB)"; + } +else + %selectionn = %selection SPC "(" @ %obj.aimtarget.source.ownername @ "\'s Target)"; + +if (%count == 0) + %target = "No targetable targets found"; +else + if (%selection == 0) + %target = "None /" SPC %count; + else + %target = %selectionn SPC %distname SPC "/" SPC %count; + +bottomPrint( %plyr.client, "Target:"SPC %target SPC"\n Payload:"SPC %loadname SPC"\n Payload cost/current => ammo:"SPC %loadcost SPC "/" SPC %obj.ammo SPC "fuel:" SPC mFloor(%dist/10) SPC "/" SPC %obj.fuel, 10, 3); +} + +function Mpm_report_scan(%plyr,%pos) +{ +%result = pulsescan(%pos,%plyr.team,50); +%line1 = " [Friendly]/[Enemy]\n"; +%line2 = "players : ["@ GetWord(%result,0) @"]/["@ GetWord(%result,1) @"]\n"; +%line3 = "vehicles: ["@ GetWord(%result,2) @"]/["@ GetWord(%result,3) @"]\n"; +bottomPrint( %plyr.client,%line1 @ %line2 @ %line3 , 10, 3); +} + +function SelectionPad::playerDismounted(%data, %obj, %player) +{ +%obj.setThreadDir(1,false); +} + +function GameBase::set_mpm_target(%obj,%target) +{ +if (!Isobject(%obj.aimtarget)) + { + //SIGN + %sign = new StaticShape(){ + dataBlock = MpmTurretTarg; + }; + %sign.team = 3; + %sign.setHeat(1); + //setTargetSensorGroup(%sign.getTarget(),3); + %sign.owner = %obj; + %obj.aimtarget = %sign; + } +if (!Isobject(%target)) + { + %pos = VectorAdd(%obj.getMuzzlePoint(0),realvec(%obj,"0 3 0")); //Changed target offset to 3 + %obj.aimtarget.setTransform(%pos SPC "1 0 0 0"); + %obj.aimtarget.targetloc = %pos; + %obj.canfire = 0; + } +else + { + %pos = %target.targetloc ? %target.targetloc : %target.getTransform(); + %baseloc = %obj.getMuzzlePoint(0); + %offset = VectorScale(VectorNormalize(VectorSub(%pos,%baseloc)),3); + %up = realvec(%obj,"0 0 1"); + %offset = VectorScale(VectorNormalize(VectorCross(VectorCross(%up,%offset),%up)),3); + %obj.aimtarget.setTransform(VectorAdd(%baseloc,%offset) SPC "1 0 0 0"); + %obj.aimtarget.source=%target; + %obj.aimtarget.targetloc = %pos; + %obj.canfire = 1; + } +%obj.Play3D(MobileBaseStationUndeploySound); +} + +////////////////////////////////LOADING STUFF/////////////////////////// + +datablock ShapeBaseImageData(MpmFuelPackImage) { + mass = 20; + emap = true; + shapeFile = "stackable4l.dts"; + item = MpmFuelPack; + mountPoint = 1; + offset = "0 -0.18 -0.5"; + + heatSignature = 0; + + stateName[0] = "Idle"; + stateTransitionOnTriggerDown[0] = "Activate"; + + stateName[1] = "Activate"; + stateScript[1] = "onActivate"; + stateTransitionOnTriggerUp[1] = "Idle"; + + isLarge = true; + maxDepSlope = 360; + deploySound = ItemPickupSound; + + minDeployDis = 0.5; + maxDeployDis = 50.0; +}; + +datablock ShapeBaseImageData(MpmFuelPackImage1):MpmFuelPackImage +{ +offset = "0 -0.75 0.25"; +}; + +datablock ItemData(MpmFuelPack) { + className = Pack; + catagory = "Deployables"; + shapeFile = "stackable4l.dts"; + mass = 5.0; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 1; + rotate = true; + image = "MpmFuelPackImage"; + pickUpName = "a Missile Fuel pack"; + heatSignature = 0; + emap = true; + }; + +datablock ShapeBaseImageData(MpmAmmoPackImage) { + mass = 20; + emap = true; + shapeFile = "bomb.dts"; + item = MpmAmmoPack; + mountPoint = 1; + offset = "0 -0.18 -0.5"; + rotation = "1 0 0 90"; + heatSignature = 0; + + stateName[0] = "Idle"; + stateTransitionOnTriggerDown[0] = "Activate"; + + stateName[1] = "Activate"; + stateScript[1] = "onActivate"; + stateTransitionOnTriggerUp[1] = "Idle"; + + isLarge = true; + maxDepSlope = 360; + deploySound = ItemPickupSound; + + minDeployDis = 0.5; + maxDeployDis = 50.0; +}; + +datablock ShapeBaseImageData(MpmAmmoPackImage1):MpmAmmoPackImage +{ +shapeFile = "bomb.dts"; +offset = "0 -0.75 1"; +rotation = "1 0 0 90"; +}; + + +datablock ItemData(MpmAmmoPack) { + className = Pack; + catagory = "Deployables"; + shapeFile = "bomb.dts"; + mass = 5.0; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 1; + rotate = true; + image = "MpmAmmoPackImage"; + pickUpName = "a Missile Ammo pack"; + heatSignature = 0; + emap = true; + }; + +function MpmAmmoPack::onPickup(%this, %obj, %shape, %amount) { + // created to prevent console errors +} + +function MpmAmmoPackImage::testNoSurfaceInRange(%item, %plyr) +{ + return (!Deployables::searchView(%plyr, $MaxDeployDistance, $TypeMasks::StaticShapeObjectType)) || (!%item.surface.isLoadClamp || %item.surface.loading); +} + +function MpmAmmoPackImage::onDeploy(%item, %plyr, %slot) +{ +MPM_LoadArmin(%item.surface); +%item.surface.mountImage(MpmAmmoPackImage1,0); +%item.surface.base.ammo += 10; +%plyr.decInventory(MpmAmmoPack, 1); +%plyr.UnMountImage(2); +} + +function MpmFuelPack::onPickup(%this, %obj, %shape, %amount) { + // created to prevent console errors +} + + +function MpmFuelPackImage::testNoSurfaceInRange(%item, %plyr) +{ + return (!Deployables::searchView(%plyr, $MaxDeployDistance, $TypeMasks::StaticShapeObjectType)) || (!%item.surface.isLoadClamp || %item.surface.loading); +} + +function MpmFuelPackImage::onDeploy(%item, %plyr, %slot) +{ +MPM_LoadArmin(%item.surface); +%item.surface.mountImage(MpmFuelPackImage1,0); +%item.surface.base.fuel += 10; +%plyr.decInventory(MpmFuelPack, 1); +%plyr.UnMountImage(2); +} + +function MPM_AddLoadArms(%obj) +{ +///baseb +if (!isobject(%obj.loadarm1)) + { + %rightarm = new StaticShape() + { + dataBlock = TurretLift; + scale = "0.25 0.5 0.8"; + }; + %rightarm.playThread(0,"activate"); + %rightarm.playThread(1,"deploy"); + %rightarm.playThread(2,"Elevate"); + + + %rightClamp = new StaticShape() + { + dataBlock = baseb; + scale = "0.5 0.5 1"; + }; + %rightclamp.isLoadClamp = 1; + %rightclamp.arm = %rightArm; + %rightClamp.base = %obj; + %rightarm.clamp = %rightClamp; + %rightarm.MountObject(%rightClamp,0); + + %pos = %obj.getTransform(); + %rot = rotadd(rotadd(rotadd(GetWords(%pos,3,6),"0 1 0" SPC $pi/2),"0 0 1" SPC $pi/2),"1 0 0" SPC -1*$pi/4); + %offset = RealVec(%obj,"-2.0 0.70 1.5"); + //%offset = RealVec(%obj,"-10 0 1"); + %rightarm.setTransform(VectorAdd(%pos,%offset) SPC %rot); + %obj.loadarm1 = %rightarm; + } +if (!isobject(%obj.loadarm2)) + { + %leftarm = new StaticShape() + { + dataBlock = TurretLift; + scale = "0.25 0.5 0.8"; + }; + %leftarm.playThread(0,"activate"); + %leftarm.playThread(1,"deploy"); + %leftarm.playThread(2,"Elevate"); + + + %leftClamp = new StaticShape() + { + dataBlock = baseb; + scale = "0.5 0.5 1"; + }; + %leftclamp.isLoadClamp = 1; + %leftclamp.arm = %leftArm; + %leftClamp.base = %obj; + %leftarm.clamp = %leftClamp; + %leftarm.MountObject(%leftClamp,0); + + %pos = %obj.getTransform(); + %rot = rotadd(rotadd(rotadd(GetWords(%pos,3,6),"0 1 0" SPC -1*$pi/2),"0 0 1" SPC -1*$pi/2),"1 0 0" SPC -1*$pi/4); + %offset = RealVec(%obj,"2.0 0.70 1.5"); + //%offset = RealVec(%obj,"-10 0 1"); + %leftarm.setTransform(VectorAdd(%pos,%offset) SPC %rot); + %obj.loadarm2 = %leftarm; + } +MPM_LoadArmOut(%obj.loadarm1.clamp); +MPM_LoadArmOut(%obj.loadarm2.clamp); +} + +function MPM_LoadArmin(%clamp) +{ +//SensorDeploySound +//MotionSensorDeploySound +//StationDeploySound +%clamp.play3d(TurretDeploySound); +%clamp.loading = 1; +//%clamp.arm.setThreaddir(0,true); +%clamp.arm.schedule(800,"setThreaddir",0,true); +%clamp.arm.setThreaddir(1,false); +//%clamp.arm.setThreaddir(2,false); +%clamp.arm.schedule(800,"setThreaddir",2,false); +schedule(2000,0,"MPM_LoadArmOut",%clamp); +} + +function MPM_LoadArmOut(%clamp) +{ +%clamp.play3d(StationDeploySound); +%clamp.unmountImage(0); +%clamp.arm.schedule(1000,"setThreaddir",0,false); +%clamp.schedule(1000,"play3d",TurretDeploySound); +%clamp.arm.setThreaddir(1,true); +%clamp.arm.schedule(1000,"setThreaddir",2,true); + +schedule(2000,%clamp,"MPM_LoadArmFinish",%clamp); +} + +function MPM_LoadArmFinish(%clamp) +{ +%clamp.loading = ""; +} + + +function MPM_RemLoadArms(%obj,%del) +{ +if (isObject(%obj.loadarm1)) + { + if (%del) + { + %obj.loadarm1.clamp.delete(); + %obj.loadarm1.delete(); + %obj.loadarm2.clamp.delete(); + %obj.loadarm2.delete(); + } + else + { + MPM_LoadArmin(%obj.loadarm1.clamp); + MPM_LoadArmin(%obj.loadarm2.clamp); + } + } +} + +/////////////////Not used.//////////////////// + +function BaseArmTurret::selectTarget(%this, %turret) +{ + %turretTarg = %turret.getTarget(); + if(%turretTarg == -1) + return; + + if ($Host::Purebuild == 1 && $TurretEnableOverride != 1) { + %turret.clearTarget(); + return; + } + + // if the turret isn't on a team, don't fire at anyone + if(getTargetSensorGroup(%turretTarg) == 0) + { + %turret.clearTarget(); + return; + } + + // stop firing if turret is disabled or if it needs power and isn't powered + if((!%turret.isPowered()) && (!%turret.needsNoPower)) + { + %turret.clearTarget(); + return; + } + + %TargetSearchMask = $TypeMasks::PlayerObjectType | $TypeMasks::VehicleObjectType | $TypeMasks::StationObjectType | $TypeMasks::GeneratorObjectType | + $TypeMasks::SensorObjectType | $TypeMasks::TurretObjectType; //$TypeMasks::StaticObjectType; + + InitContainerRadiusSearch(%turret.getMuzzlePoint(0), + %turret.getMountedImage(0).attackRadius, + %TargetSearchMask); + + while ((%potentialTarget = ContainerSearchNext()) != 0) { + if (%potentialtarget) { + %potTargTarg = %potentialTarget.getTarget(); + if (%turret.isValidTarget(%potentialTarget) + && (getTargetSensorGroup(%turretTarg) != getTargetSensorGroup(%potTargTarg)) + && (getTargetSensorGroup(%potTargTarg) != 0)) { + %turret.setTargetObject(%potentialTarget); + return; + } + } + } +} + +///////////////////////////BEACON STUFF/////////////////////////// + +datablock ShapeBaseImageData(MPM_BeaconPackImage) +{ + shapeFile = "turret_belly_base.dts"; + item = MPM_BeaconPack; + mountPoint = 1; + offset = "0 0 0"; + rotation = "1 0 0 90"; + emap = true; + deployed = Mpm_Beacon; + + stateName[0] = "Idle"; + stateTransitionOnTriggerDown[0] = "Activate"; + + stateName[1] = "Activate"; + stateScript[1] = "onActivate"; + stateTransitionOnTriggerUp[1] = "Idle"; + + isLarge = false; + maxDepSlope = 360; + deploySound = ItemPickupSound; + + minDeployDis = 0.5; + maxDeployDis = 50.0; +}; + +datablock ItemData(MPM_BeaconPack) +{ + className = Pack; + catagory = "Deployables"; + shapeFile = "turret_belly_base.dts"; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 2; + rotate = true; + image = "MPM_BeaconPackImage"; + pickUpName = "an beacon pack"; + + computeCRC = true; + +}; + +datablock StaticShapeData(Mpm_Beacon_Ghost) : StaticShapeDamageProfile { + + shapeFile = "stackable4m.dts"; + maxDamage = 0.5; + destroyedLevel = 0.5; + disabledLevel = 0.3; + +}; + + + +function MPM_BeaconPack::onPickup(%this, %obj, %shape, %amount) +{ + // created to prevent console errors +} + +function MPM_BeaconPackImage::onDeploy(%item, %plyr, %slot) { + + %playerVector = vectorNormalize(-1 * getWord(%plyr.getEyeVector(),1) SPC getWord(%plyr.getEyeVector(),0) SPC "0"); + %item.surfaceNrm2 = %playerVector; + %rot = fullRot(%item.surfaceNrm,%item.surfaceNrm2); + %rot = rotAdd(%rot,"1 0 0 3.14"); + %beacon = new StaticShape() + { + dataBlock = Mpm_Beacon; + }; + %ghost = new StaticShape() + { + dataBlock = Mpm_Beacon_Ghost; + scale = "1 1 0.2"; + }; + %beacon.ghost = %ghost; + %ghost.base = %beacon; + + %beacon.setTransform(%item.surfacePt SPC %rot); + %ghost.setTransform(%item.surfacePt SPC %rot); + + %beacon.team = %plyr.client.team; + %beacon.setOwner(%plyr); + %beacon.ownername = %plyr.client.namebase; + %ghost.team = %plyr.client.team; + %ghost.setOwner(%plyr); + + %beacon.addtoMPMGroup(2); + Mpm_Link(%beacon); + + + // play the deploy sound + serverPlay3D(%item.deploySound, %beacon.getTransform()); + + addDSurface(%item.surface,%deplObj); + + %plyr.getMountedImage(2).used++; + if (%plyr.getMountedImage(2).used>2) + { + %plyr.getMountedImage(2).used = 0; + %plyr.decInventory(MPM_BeaconPack, 1); + %plyr.UnMountImage(2); + } + return %beacon; +} + +function MPM_BeaconPackImage::testObjectTooClose(%item,%surfacePt,%plyr) { +return (GetWord(%plyr.closestmpmbeacon(0),1)<25 && %plyr.closestmpmbeacon(0)); +} + +function Mpm_Beacon_Ghost::disassemble(%data,%plyr,%obj) { +%base = %obj.base; +%base.destroyed=1; +if (IsObject(%base.link1)) + Mpm_Link(%base.link1,%obj); +if (IsObject(%base.link2)) + Mpm_Link(%base.link2,%obj); +Parent::onDestroyed(%this, %base, %prevState); +if (IsObject(%base.emitter)) +%base.emitter.schedule(500,"delete"); + +%base.schedule(500, "delete"); + +parent::disassemble(%data,%plyr,%obj); +} + +function GameBase::putpack(%obj) +{ +%i = new Item() + { + dataBlock = Mpm_BeaconPack; + }; +%i.setTransform(%obj.getTransform()); +} + +datablock StaticShapeData(Mpm_Beacon) : StaticShapeDamageProfile { + className = "targeting"; + shapeFile = "turret_belly_base.dts"; + + maxDamage = 0.5; + destroyedLevel = 0.5; + disabledLevel = 0.3; + + explosion = HandGrenadeExplosion; + expDmgRadius = 1.0; + expDamage = 0.05; + expImpulse = 200; + + dynamicType = $TypeMasks::StaticShapeObjectType; + deployedObject = true; + cmdCategory = "DSupport"; + cmdIcon = CMDSensorIcon; + cmdMiniIconName = "commander/MiniIcons/com_deploymotionsensor"; + targetNameTag = 'Deployed mpm Beacon'; + deployAmbientThread = true; + debrisShapeName = "debris_generic_small.dts"; + debris = DeployableDebris; + heatSignature = 0; +}; + +datablock ParticleData(MpmGreenParticle) +{ + dragCoeffiecient = 0.0; + gravityCoefficient = 0.0; + inheritedVelFactor = 1.0; + + lifetimeMS = 800; + lifetimeVarianceMS = 0; + + spinRandomMin = 0.0; + spinRandomMax = 0.0; + windcoefficient = 0; + textureName = "flarebase"; + colors[0] = "0.2 1 0.2 0"; + colors[1] = "0.2 1 0.2 1"; + colors[2] = "0.2 1 0.2 1"; + colors[3] = "0.2 1 0.2 0"; + + sizes[0] = 1; + sizes[1] = 0.75; + sizes[2] = 0.5; + sizes[3] = 0.25; + + times[0] = 0.0; + times[1] = 0.25; + times[2] = 0.5; + times[3] = 1; + + +}; + +datablock ParticleData(MpmRedParticle):MpmGreenParticle +{ + textureName = "flarebase"; + colors[0] = "1 0.2 0 0"; + colors[1] = "1 0.2 0 1"; + colors[2] = "1 0.2 0 1"; + colors[3] = "1 0.2 0 0"; + + sizes[0] = 1; + sizes[1] = 0.75; + sizes[2] = 0.5; + sizes[3] = 0.25; + + times[0] = 0.0; + times[1] = 0.25; + times[2] = 0.5; + times[3] = 1; +}; + +datablock ParticleEmitterData(MpmGreenEmitter) +{ + lifetimeMS = 10; + ejectionPeriodMS = 100; + periodVarianceMS = 0; + + ejectionVelocity = 0.5; + velocityVariance = 0.0; + ejectionoffset = 0; + thetaMin = 0.0; + thetaMax = 0.0; + + + orientParticles = false; + orientOnVelocity = false; + + particles = "MpmGreenParticle"; +}; + +datablock ParticleEmitterData(MpmRedEmitter):MpmGreenEmitter +{ +particles = "MpmRedParticle"; +ejectionoffset = 0; +}; + +function GameBase::Mpm_Beacon_Add(%obj) +{ +%pos = GetWords(%obj.getTransform(),0,2); +%rot = "1 0 0 3.14"; +%beacon = new StaticShape() + { + dataBlock = Mpm_Beacon; + }; +%beacon.setTransform(%pos SPC %rot); +%beacon.team = %obj.client.team; +%beacon.setOwner(%obj); + +%beacon.addtoMPMGroup(2); +Mpm_Link(%beacon); +} + +function Mpm_Beacon::onDestroyed(%this, %obj, %prevState) +{ +%obj.destroyed=1; +if (IsObject(%obj.link1)) + Mpm_Link(%obj.link1,%obj); +if (IsObject(%obj.link2)) + Mpm_Link(%obj.link2,%obj); +Parent::onDestroyed(%this, %obj, %prevState); +if (IsObject(%obj.emitter)) +%obj.emitter.schedule(500,"delete"); +if (IsObject(%obj.ghost)) +%obj.ghost.schedule(500,"delete"); +%obj.schedule(500, "delete"); +} + + +function Mpm_Link(%obj,%exclude) +{ +if (!isObject(%obj) || Mpm_checkLink(%obj) || %obj.destroyed) + return ""; + +%pos = %obj.getTransform(); +%maxrange = 200; //max link range boosted from 100 to 200 +%mask = $TypeMasks::StaticShapeObjectType; + +InitContainerRadiusSearch(%pos,%maxrange,%mask); +%amount=0; + while ((%target = ContainerSearchNext()) != 0) + { + if (mpm_beacons.isMember(%target) && !%target.destroyed) + { + %mpmlist[%amount] = %target; + %amount++; + } + } + + +for (%i=0;%i<%amount;%i++) + { + %link1 = %mpmlist[%i]; + %pos1= %link1.getTransform(); + if (isObject(%link1) && %link1 != %obj && %link1 != %exclude && !%link1.linked && VectorDist(%pos,%pos1) < %maxrange) + { + for (%j=%i+1;%i<%amount;%i++) + { + %link2 = %mpmlist[%i]; + %pos2= %link2.getTransform(); + if (isObject(%link2) && %link2 != %obj && %link2 != %exclude && %link2 != %link1 && !%link2.linked && VectorDist(%pos,%pos2) < %maxrange && VectorDist(%pos1,%pos2) < %maxrange) + { + Mpm_linkup(%obj,%link1,%link2); + } + } + } + } +Mpm_checkLink(%obj); +} + +function Mpm_linkup(%b1,%b2,%b3) +{ +%b1.link1 = %b2; +%b1.link2 = %b3; +%b1.linked = 1; +Mpm_checkLink(%b1); +%b2.link1 = %b1; +%b2.link2 = %b3; +%b2.linked = 1; +Mpm_checkLink(%b2); +%b3.link1 = %b1; +%b3.link2 = %b2; +%b3.linked = 1; +Mpm_checkLink(%b3); +} + +function Mpm_nolink(%obj) +{ +return !isObject(%obj) || %obj.destroyed; +} + +function Mpm_checkLink(%obj) +{ +if (IsObject(%obj.emitter)) + %obj.emitter.delete(); +if (!%obj.linked || Mpm_nolink(%obj.link1) || Mpm_nolink(%obj.link2) ) + { + %obj.linked = 0; + %obj.link1 = 0; + %obj.link2 = 0; + %obj.emitter=CreateEmitter(VectorAdd(%obj.getTransform(),realvec(%obj,"0 0 -1")),MpmRedEmitter,"1 0 0 0"); + return ""; + } +else + { + %pos = %obj.getTransform(); + %pos1 = %obj.link1.getTransform(); + %pos2 = %obj.link2.getTransform(); + %obj.targetloc = VectorScale(VectorAdd(VectorAdd(%pos1,%pos2),%pos),1/3); + %nrm = VectorNormalize(VectorSub(%obj.targetloc,%pos)); + %rot = fullrot(%nrm,"0 0 1"); + %obj.emitter=CreateEmitter(VectorAdd(%pos,realvec(%obj,"0 0 -1")),MpmGreenEmitter,%rot); + return 1; + } +} + + + +function GameBase::checkMpmLink(%obj,%exclude) +{ +%location = %obj.getTransform(); +%range = 200; //max link range boosted from 100 to 200 +%mask = $TypeMasks::StaticShapeObjectType; +%done = 0; +InitContainerRadiusSearch(%location,%range,%mask); + + while ((%target = ContainerSearchNext()) != 0 && %done != 2) + { + if (mpm_beacons.isMember(%target)) + { + if (%target != %obj && %target != %exclude) + { + if (!isObject(%obj.link1) || %obj.link1 == %exclude) //Do we have an link1 + { + %obj.link1 = 0; //Totally remove it. + if (%obj.link2 != %target) //We don't already have it right? + if (%target.askMpmLink(%obj,%exclude)) //Can we have you? + { + %obj.MpmLink(%target,1,%exclude); //Take + %done++; + } + } + if (!isObject(%obj.link2) || %obj.link2 == %exclude) + { + %obj.link2 = 0; + if (%obj.link1 != %target) + if (%target.askMpmLink(%obj,%exclude)) + { + %obj.MpmLink(%target,2,%exclude); + %done++; + } + } + } + } + } +if (%done == 0) + %obj.MpmLink(); +} + + +function GameBase::AskMpmLink(%target,%sender,%override) +{ +if (%target.link1 == %sender || %target.link2 == %sender) + return 1; +if (!IsObject(%target.link1) || %target.link1 == %override) + { + %target.MpmLink(%sender,1,%override); + return 1; + } +if (!IsObject(%target.link2) || %target.link2 == %override) + { + %target.MpmLink(%sender,2,%override); + return 1; + } +return 0; +} + +function GameBase::MpmLink(%obj,%link,%part,%exclude) +{ +if (IsObject(%obj.emitter)) + %obj.emitter.delete(); +%location = %obj.getTransform(); +%linkedto=0; +if (%part == 1) + %obj.link1=%link; +else if (%part == 2) + %obj.link2=%link; +if (isObject(%obj.link1) && %obj.link1 != %exclude) + %linkedto++; +if (isObject(%obj.link2) && %obj.link2 != %exclude) + %linkedto++; +%obj.linkedto = %linkedto; + +if (!%obj.destroyed) + { +if (%linkedto==2) + { + %pos1 = %obj.link1.getTransform(); + %pos2 = %obj.link2.getTransform(); + %obj.targetloc = VectorScale(VectorAdd(VectorAdd(%pos1,%pos2),%location),1/3); + %nrm = VectorSub(%obj.targetloc,%location); + %rot = fullrot(%nrm,"0 0 1"); + %obj.emitter=CreateEmitter(VectorAdd(%location,realvec(%obj,"0 0 -1")),MpmGreenEmitter,%rot); + } +else + { + %obj.emitter=CreateEmitter(VectorAdd(%location,realvec(%obj,"0 0 -1")),MpmRedEmitter,"1 0 0 0"); + } + } +} + +function GetMPMTargetList(%team,%pos,%min,%max) +{ +if (!isObject(MpmGroup)) + return ""; +for( %c = 0; %c < mpm_beacons.getCount(); %c++ ) + { + %beacon = mpm_beacons.getObject(%c); + if (%beacon.team == %team || $mpm::targetenemies) + { + if (findWord(%targetlist,%beacon.link1 SPC %beacon.link2) $= "" && %beacon.linked) //Only want beacons that are linked + { + %dist = VectorDist(%beacon.targetloc,%pos); + if (%dist > %min && %dist < %max) // Hey not too close... too far is bad too + %targetlist = listAdd(%targetlist,%beacon); + } + else if (%beacon.end == %beacon.targetloc && %beacon.islaser) //What have we here?.. a laser target perhaps? + { + %dist = VectorDist(%beacon.targetloc,%pos); + if (%dist > %min && %dist < %max) + %targetlist = listAdd(%targetlist,%beacon); + } + + } + } +if ($mpm::targetmpbs) //Nifty lil feature requested by peeps. + for( %c = 0; %c < mpm_turrets.getCount(); %c++ ) + { + %beacon = mpm_turrets.getObject(%c); + if (%turret.team != %team || $teamDamage) + { + %dist = VectorDist(%beacon.getTransform(),%pos); //Need transform for location :D + if (%dist > %min && %dist < %max) + %targetlist = listAdd(%targetlist,%beacon); + } + } + +return %targetlist; +} + +function Gamebase::addToMPMGroup(%obj,%set) +{ + if (!isObject(MpmGroup)) + { + %main = new SimGroup("MpmGroup"); + MissionCleanup.add(%main); + %miss = new Simgroup("mpm_Missiles"); + %turrets = new Simgroup("mpm_turrets"); + %beacons = new Simgroup("mpm_beacons"); + %main.add(%miss); + %main.add(%turrets); + %main.add(%beacons); + } +if (IsObject(%obj)) + { + if (%set == 1) + Mpm_Turrets.add(%obj); + else if (%set == 2) + mpm_beacons.add(%obj); + else + mpm_Missiles.add(%obj); + } +} + +function GameBase::remfromMpmGroup(%obj,%set) +{ +if (!isObject(MpmGroup)) + { + %main = new SimGroup("MpmGroup"); + MissionCleanup.add(%main); + %miss = new Simgroup("mpm_Missiles"); + %turrets = new Simgroup("mpm_turrets"); + %beacons = new Simgroup("mpm_beacons"); + %main.add(%miss); + %main.add(%turrets); + %main.add(%beacons); + } +if (IsObject(%obj)) + { + if (%set == 1 && Mpm_turrets.IsMember(%obj)) + Mpm_turrets.remove(%obj); + else if (%set == 2 && Mpm_beacons.IsMember(%obj)) + Mpm_beacons.remove(%obj); + else if (Mpm_Missiles.IsMember(%obj)) + Mpm_Missiles.remove(%obj); + } +} + +function GameBase::closestmpmbeacon(%obj,%exclude) +{ +%location = %obj.getTransform(); +if (!mpm_beacons.getCount()) + return ""; + +%tbeacon = ""; +for( %c = 0; %c < mpm_beacons.getCount(); %c++ ) + { + %beacon = mpm_beacons.getObject(%c); + if (%beacon != %obj && %beacon != %exclude && %beacon.team == %obj.team) + { + %pos = pos(%beacon); + %dist = vectorDist(%location,%pos); + if (!%dis || %dist < %dis) + { + %tbeacon = %beacon; + %dis = %dist; + } + } + } +return %tbeacon SPC %dist; +} + +function TargetingLaserImage::Onfire(%data,%obj,%slot) { +%p = Parent::onFire(%data, %obj, %slot); +%p.setTarget(%obj.team); +if (%obj.getMountedImage(2) && %obj.getMountedImage(2).getName() $= MPM_BeaconPackImage) + { + bottomPrint( %obj.client, "Keep aiming the targetlaser at the same spot\n to maintain a temperary Missile target", 10, 2); + %obj.laser = %p; + %p.player = %obj; + %end =%obj.TraceLaser(); + if (%end != -1) + %obj.laser.end=%end; + %obj.schedule(5000,"ValidateLaser"); + } +} + +function GameBase::TraceLaser(%obj) +{ +%mask = $TypeMasks::TerrainObjectType | $TypeMasks::InteriorObjectType | $TypeMasks::VehicleObjectType |$TypeMasks::StaticShapeObjectType; +%start = %obj.getMuzzlePoint(0); +%end = VectorAdd(%start,VectorScale(%obj.getMuzzleVector(0),3000)); +%res = ContainerRayCast(%start,%end,%mask, %obj); +if (%res) + { + return GetWords(%res,1,3); + } +else + return -1; +} + +function GameBase::ValidateLaser(%obj) +{ +if (IsObject(%obj.laser)) + { + %end = %obj.traceLaser(); + if (%end != %obj.laser.end || %obj.laser.end==-1) + { + %obj.laser.remfromMpmGroup(2); + %obj.laser.end=%end; + %obj.laser.firedat =0; + } + else + { + %obj.laser.islaser = 1; + %obj.laser.addtoMpmGroup(2); + %obj.play3d(LaserTargetSound); + if (%obj.laser.firedat) + %text = "Missiles lauched at your laser target:"@%obj.laser.firedat; + else + %text = "Noting lauched so far."; + bottomPrint( %obj.client, "Laser stable, temporary target maintained.\n Keep the laser at it\'s current target, to maintain the target.\n" SPC %text , 3, 3); + + %obj.laser.targetloc = %obj.laser.end; + %obj.laser.team = %obj.team; + } + %obj.schedule(3000,"ValidateLaser"); + } +} + +datablock ShockwaveData(PulseWave) { + className = "ShockwaveData"; + scale = "1 1 1"; + delayMS = "0"; + delayVariance = "0"; + lifetimeMS = "1000"; + lifetimeVariance = "0"; + width = "1"; + numSegments = "60"; + numVertSegments = "1"; + velocity = "30"; + height = "20"; + verticalCurve = "5"; + acceleration = "5"; + times[0] = "0"; + times[1] = "0.25"; + times[2] = "0.75"; + times[3] = "1"; + colors[0] = "1.000000 0.000000 0.000000 1.000000"; //1.0 0.9 0.9 + colors[1] = "1.000000 0.000000 0.000000 1.000000"; //0.6 0.6 0.6 + colors[2] = "1.000000 0.000000 0.000000 1.000000"; //0.6 0.6 0.6 + colors[3] = "1.000000 0.000000 0.000000 0.000000"; + texture[0] = "gamegrid"; + texture[1] = "gamegrid"; + texWrap = "7"; + is2D = "1"; + mapToTerrain = "0"; + orientToNormal = "1"; + renderBottom = "1"; + renderSquare = "0"; +}; + +datablock ExplosionData(PulseExplosion):BaseExplosion //From blast.cs + { + Shockwave = "PulseWave"; + }; + + +datablock TracerProjectileData(PulseProjectile):BaseProjectile + { + Explosion = "PulseExplosion"; + }; + +function pulse(%pos) +{ +schedule(200,0,"Serverplay3D",FlashGrenadeExplosionSound,%pos); +for (%i=0;%i<5;%i++) + { + + schedule(%i*200,0,"shockwave",%pos,"0 0 1",PulseProjectile); + } +} + +function obspulse(%pos,%client,%time) +{ +if ( !isObject( %client.comCam ) ) + { + %client.comCam = new Camera() + { + dataBlock = CommanderCamera; + }; + MissionCleanup.add(%client.comCam); + } +%sign = new StaticShape(){ +dataBlock = MpmTurretTarg; +}; +%sign.setTransform(VectorAdd(%pos,"0 0 5") SPC "1 0 0 -1"); +%client.comCam.setTransform(VectorAdd(%pos,"0 0 50")); +%client.comCam.setOrbitMode(%sign,%pos,-10,50,-10); +%client.setControlObject(%client.comCam); +commandToClient(%client, 'CameraAttachResponse', true); +%client.schedule(%time,"setControlObject",%client.player); +commandToClient(%client, 'ControlObjectResponse', true, getControlObjectType(%client.comcam,%client.player)); +messageClient(%client, 'CloseHud', "", 'inventoryScreen'); +schedule(%time,%client,"serverCmdResetControlObject",%client); +%sign.schedule(%time+100,"delete"); +} + +function pulsescan(%pos,%team,%range) +{ +%mask = $TypeMasks::PlayerObjectType |$TypeMasks::VehicleObjectType ; +%done = 0; +InitContainerRadiusSearch(%pos,%range,%mask); +%epl = 0; +%fpl = 0; +%evh = 0; +%fvh = 0; + while ((%target = ContainerSearchNext()) != 0) + { + if (%target.getType() & $TypeMasks::PlayerObjectType) + { + if (%target.team != %team) + %epl++; + else + %fpl++; + } + else if(%target.getType() & $TypeMasks::VehicleObjectType) + { + if (%target.team != %team) + %evh++; + else + %fvh++; + } + } +return %fpl SPC %epl SPC %fvh SPC %evh; +} diff --git a/scripts/MPM/Mpm_BE.cs b/scripts/MPM/Mpm_BE.cs new file mode 100644 index 0000000..776d082 --- /dev/null +++ b/scripts/MPM/Mpm_BE.cs @@ -0,0 +1,272 @@ + +if ($mpm_BE != 1) + { + //$mpm_load[$mpm_loads] = Mpm_Base_Load; + //$mpm_loads++; + $mpm_load[$mpm_loads] = Mpm_BBom_Load; + $mpm_loads++; + $mpm_load[$mpm_loads] = Mpm_BMis_Load; + $mpm_loads++; + $mpm_load[$mpm_loads] = Mpm_BMor_Load; + $mpm_loads++; + $mpm_BE = 1; + } + + + +datablock ItemData(Mpm_Base_Load) +{ + cost = 40; + missile = Mpm_B_MIS1; + name = "[Weapon] Base Explosion"; + friendly = 0; +}; + +datablock ItemData(Mpm_BBom_Load):Mpm_Base_Load +{ + cost = 75; + name = "[Cluster] Bomber Run"; + missile = Mpm_B_MIS1; + offset = "0 100"; + slot = 4; +}; + +datablock ItemData(Mpm_BMis_Load):Mpm_Base_Load +{ + cost = 50; + name = "[Cluster] Cluster Missile"; + missile = Mpm_B_MIS1; + offset = "0 0"; + slot = 4; +}; + +datablock ItemData(Mpm_BMor_Load):Mpm_Base_Load +{ + cost = 75; + name = "[Cluster] Mortar dump"; + missile = Mpm_B_MIS1; + offset = "0 100"; + slot = 4; +}; + +datablock AudioDescription(AudioMassiveExplosion) { + volume = "1"; + isLooping = "0"; + is3D = "1"; + minDistance = "500"; + maxDistance = "9999"; + coneInsideAngle = "360"; + coneOutsideAngle = "360"; + coneOutsideVolume = "1"; + coneVector = "0 0 1"; + environmentLevel = "1"; + loopCount = "-1"; + minLoopGap = "0"; + maxLoopGap = "0"; + type = "3"; +}; + +datablock AudioProfile(Mpm_BE_Sound) { + fileName = "fx/weapons/mortar_explode.wav"; + description = "AudioMassiveExplosion"; + Preload = "1"; +}; + +datablock ParticleData(Mpm_BE_PA) { + dragCoefficient = "0.6"; + windCoefficient = "0"; + gravityCoefficient = "0"; + inheritedVelFactor = "0"; + constantAcceleration = "0"; + lifetimeMS = "7000"; + lifetimeVarianceMS = "2000"; + spinSpeed = "0"; + spinRandomMin = "-500"; + spinRandomMax = "500"; + useInvAlpha = "0"; + animateTexture = "0"; + framesPerSec = "1"; + textureName = "special/expFlare"; + animTexName[0] = "special/expFlare"; + colors[0] = "1.000000 1.000000 1.000000 0.900000"; + colors[1] = "1.000000 0.400000 0.000000 0.300000"; + colors[2] = "1.000000 0.300000 0.000000 0.000000"; + colors[3] = "1.000000 1.000000 1.000000 1.000000"; + sizes[0] = "75"; + sizes[1] = "250"; + sizes[2] = "400"; + sizes[3] = "1"; + times[0] = "0"; + times[1] = "0.7"; + times[2] = "1"; + times[3] = "2"; +}; + + + +datablock ParticleEmitterData(Mpm_BE_PE) { + className = "ParticleEmitterData"; + ejectionPeriodMS = "3"; + periodVarianceMS = "0"; + ejectionVelocity = "57"; + velocityVariance = "20"; + ejectionOffset = "6"; + thetaMin = "0"; + thetaMax = "110"; + phiReferenceVel = "0"; + phiVariance = "360"; + overrideAdvance = "0"; + orientParticles = "0"; + orientOnVelocity = "1"; + particles = "Mpm_BE_PA"; + lifetimeMS = "3600"; + lifetimeVarianceMS = "0"; + useEmitterSizes = "0"; + useEmitterColors = "0"; + overrideAdvances = "0"; +}; + +datablock ExplosionData(Mpm_BE) { + className = "ExplosionData"; + soundProfile = "Mpm_BE_Sound"; + faceViewer = "0"; + particleDensity = "10"; + particleRadius = "1"; + explosionScale = "1 1 1"; + playSpeed = "1"; + emitter[0] = "Mpm_BE_PE"; + shockwaveOnTerrain = "0"; + debrisThetaMin = "0"; + debrisThetaMax = "90"; + debrisPhiMin = "0"; + debrisPhiMax = "360"; + debrisNum = "1"; + debrisNumVariance = "0"; + debrisVelocity = "2"; + debrisVelocityVariance = "0"; + delayMS = "0"; + delayVariance = "0"; + lifetimeMS = "1000"; + lifetimeVariance = "0"; + offset = "0"; + times[0] = "0"; + times[1] = "1"; + times[2] = "1"; + times[3] = "1"; + sizes[0] = "1 1 1"; + sizes[1] = "1 1 1"; + sizes[2] = "1 1 1"; + sizes[3] = "1 1 1"; + shakeCamera = "0"; + camShakeFreq = "10 10 10"; + camShakeAmp = "1 1 1"; + camShakeDuration = "1.5"; + camShakeRadius = "10"; + camShakeFalloff = "10"; +}; + +datablock TracerProjectileData(Mpm_BE_PR):Mpm_G_PR { + Explosion = "Mpm_BE"; + }; + + +function Mpm_BBom_Load::Stage2(%data,%p) +{ +if (IsObject(%p)) + { + %p2 = parent::Stage2(%data,%p); + Cancel(%p2.stage2); + %p2.stage2 = %data.schedule((%p2.s2time-5000),"AtTarget",%p2); + } +} + +function Mpm_Bbom_Load::AtTarget(%data,%p) +{ +if (IsObject(%p)) + { + %speed = GetWords(%p.predict(),3,5); + %p.schedule(100,"Mpm_BomberRun"); + } +} + + +function Mpm_Bmis_Load::Stage2(%data,%p) +{ +if (IsObject(%p)) + { + %p2 = parent::Stage2(%data,%p); + Cancel(%p2.stage2); + %p2.stage2 = %data.schedule((%p2.s2time-5000),"AtTarget",%p2); + } +} + +function Mpm_Bmis_Load::AtTarget(%data,%p) +{ +if (IsObject(%p)) + { + %speed = GetWords(%p.predict(),3,5); + %p.schedule(250,"Mpm_MissileRun"); + } +} + + +function Mpm_Bmor_Load::Stage2(%data,%p) +{ +if (IsObject(%p)) + { + %p2 = parent::Stage2(%data,%p); + Cancel(%p2.stage2); + %p2.stage2 = %data.schedule((%p2.s2time-5000),"AtTarget",%p2); + } +} + +function Mpm_Bmor_Load::AtTarget(%data,%p) +{ +if (IsObject(%p)) + { + %speed = GetWords(%p.predict(),3,5); + %p.schedule(100,"Mpm_MortarRun"); + } +} + + +function SeekerProjectile::Mpm_BomberRun(%p) +{ +%speed = VectorNormalize(GetWords(%p.predict(),3,5)); +%adjust = VectorCross(%speed,"0 0 1"); +%adjust = VectorAdd(VectorScale(VectorCross(%adjust,%speed),GetRandom()*2-1),VectorScale(%adjust,GetRandom()*2-1)); +%p2=BomberBomb.Create(%p.getWorldBoxCenter(),"0 0 -1",VectorScale(VectorAdd(%speed,%adjust),25)); +%p.schedule(250,"Mpm_bomberRun"); +} + +function SeekerProjectile::Mpm_MissileRun(%p) +{ +%speed = GetWords(%p.predict(),3,5); +%dir = VectorNormalize(%speed); +%for = VectorScale(%dir,-89.3); +%left = VectorNormalize(VectorCross("0 0 1",%for)); +%up = VectorNormalize(VectorCross(%for,%left)); +%var = VectorAdd(VectorScale(%left,getRandom()*20-10),VectorScale(%up,getRandom()*20-10)); +%vel = VectorAdd(%for,%var); +ShoulderMissile.create(%p.getWorldBoxCenter(),%dir,%vel); +%p.schedule(100,"Mpm_MissileRun"); +} + +function SeekerProjectile::Mpm_MortarRun(%p) +{ +%speed = VectorNormalize(GetWords(%p.predict(),3,5)); +%adjust = VectorCross(%speed,"0 0 1"); +%adjust = VectorAdd(VectorScale(VectorCross(%adjust,%speed),GetRandom()*2-1),VectorScale(%adjust,GetRandom()*2-1)); + +%p2=MortarShot.Create(%p.getWorldBoxCenter(),"0 0 -1",VectorScale(VectorAdd(%speed,%adjust),25)); +%p.schedule(150,"Mpm_MortarRun"); +} + +function Mpm_Base_Load::Explode(%data,%p,%pos) +{ +if (IsObject(%p)) + { + PlayExplosion(%pos,"Mpm_BE_PR","0 0 -1"); + RadiusExplosion(%p, %pos, 50, 5, 5000, %p.owner, $DamageType::Missile); + } +} \ No newline at end of file diff --git a/scripts/MPM/Mpm_SE.cs b/scripts/MPM/Mpm_SE.cs new file mode 100644 index 0000000..ea44108 --- /dev/null +++ b/scripts/MPM/Mpm_SE.cs @@ -0,0 +1,766 @@ +///Telleport missile + +datablock ParticleData(Mpm_B_MIS_P1) +{ + dragCoeffiecient = 0.0; + gravityCoefficient = 0.0; + inheritedVelFactor = 1.0; + + lifetimeMS = 8000; + lifetimeVarianceMS = 0; + + spinRandomMin = 0.0; + spinRandomMax = 0.0; + windcoefficient = 0; + textureName = "special/lensflare/flare00"; + + colors[0] = "0.3 0.3 1.0 0"; + colors[1] = "0.3 0.3 1.0 1"; + colors[2] = "0.3 0.3 1.0 1"; + colors[3] = "0.3 0.3 1.0 0.1"; + + sizes[0] = 0; + sizes[1] = 10; + sizes[2] = 5; + sizes[3] = 20; + + times[0] = 0.1; + times[1] = 0.2; + times[2] = 0.3; + times[3] = 1; + +}; + +datablock ParticleEmitterData(Mpm_B_MIS_PE1) +{ + lifetimeMS = 10; + ejectionPeriodMS = 10; + periodVarianceMS = 0; + + ejectionVelocity = 1; + velocityVariance = 0.0; + ejectionoffset = 0; + thetaMin = 0.0; + thetaMax = 0.0; + + phiReferenceVel = "0"; + phiVariance = "360"; + orientParticles = true; + orientOnVelocity = true; + + particles = "Mpm_B_MIS_P1"; +}; + +datablock ParticleData(Mpm_B_MIS_P2):Mpm_B_MIS_P1 +{ + dragCoeffiecient = 0.0; + gravityCoefficient = 0.0; + inheritedVelFactor = 1.0; + + lifetimeMS = 1500; + lifetimeVarianceMS = 0; + + spinRandomMin = 0.0; + spinRandomMax = 0.0; + windcoefficient = 0; + textureName = "special/lensflare/flare00"; + + colors[0] = "0.3 0.3 1.0 0"; + colors[1] = "0.3 0.3 1.0 1"; + colors[2] = "0.3 0.3 1.0 1"; + colors[3] = "0.3 0.3 1.0 0.1"; + + sizes[0] = 0; + sizes[1] = 8; + sizes[2] = 8; + sizes[3] = 20; + + times[0] = 0.3; + times[1] = 0.5; + times[2] = 0.8; + times[3] = 1; + +}; + +datablock ParticleEmitterData(Mpm_B_MIS_PE2):Mpm_B_MIS_PE1 +{ + lifetimeMS = 10; + ejectionPeriodMS = 50; + periodVarianceMS = 0; + + ejectionVelocity = 0.1; + velocityVariance = 0.0; + ejectionoffset = 0; + thetaMin = 140.0; + thetaMax = 160.0; + + + orientParticles = false; + orientOnVelocity = false; + + particles = "Mpm_B_MIS_P2"; +}; + + + + +datablock SeekerProjectileData(Mpm_B_MIS):MpmMissile1 +{ + casingShapeName = "weapon_missile_casement.dts"; + projectileShapeName = "turret_muzzlePoint.dts"; + + + explosion = "GrenadeExplosion"; + splash = MissileSplash; + + baseEmitter = Mpm_B_MIS_PE1; + delayEmitter = Mpm_B_MIS_PE2; + puffEmitter = MissilePuffEmitter; + bubbleEmitter = GrenadeBubbleEmitter; + bubbleEmitTime = 1.0; + + exhaustEmitter = MissileLauncherExhaustEmitter; + exhaustTimeMs = 300; + exhaustNodeName = "muzzlePoint1"; + + lifetimeMS = -1; + muzzleVelocity = 0.1; + maxVelocity = 80000; + turningSpeed = 0.0; + acceleration = 3; + scale = "1 1 1"; + proximityRadius = 3; + + terrainAvoidanceSpeed = 180; + terrainScanAhead = 25; + terrainHeightFail = 12; + terrainAvoidanceRadius = 100; + + flareDistance = 0; + flareAngle = 0; + + sound = HAPCFlyerThrustSound; + //BomberFlyerThrustSound; + explodeOnDeath = "1"; + hasLight = true; + lightRadius = 10.0; + lightColor = "0 0 1"; + + useFlechette = false; + flechetteDelayMs = 550; + casingDeb = FlechetteDebris; + + explodeOnWaterImpact = true; +}; + +//Multi WarHead Missiles + +datablock ParticleData(Mpm_B_MIS1_P1) +{ + dragCoefficient = 5; + gravityCoefficient = 0; + inheritedVelFactor = 0.0; + constantAcceleration = 0; + lifetimeMS = 30000; + lifetimeVarianceMS = 0; + textureName = "special/BigSpark"; + windcoefficient = 0; + colors[0] = "0.6 0.6 0.6 1"; + colors[1] = "0.6 0.6 0.6 1"; + colors[2] = "0.6 0.6 0.6 1"; + colors[3] = "0.2 0.2 0.2 1"; + sizes[0] = 0; + sizes[1] = 15; + sizes[2] = 5; + sizes[3] = 0; + times[0] = 0.0; + times[1] = 0.04; + times[2] = 0.08; + times[3] = 1; + +}; + +datablock ParticleEmitterData(Mpm_B_MIS1_PE1) +{ + lifetimeMS = 10; + ejectionPeriodMS = 10; + periodVarianceMS = 0; + + ejectionVelocity = 10; + velocityVariance = 0.0; + ejectionoffset = 2; + thetaMin = 180.0; + thetaMax = 180.0; + + phiReferenceVel = "0"; + phiVariance = "0"; + orientParticles = true; + orientOnVelocity = false; + + particles = "Mpm_B_MIS1_P1"; +}; + +datablock ParticleData(Mpm_B_MIS1_P2):Mpm_B_MIS_P1 +{ + dragCoeffiecient = 0.0; + gravityCoefficient = 0.0; + inheritedVelFactor = 1.0; + constantAcceleration = -0.25; + lifetimeMS = 10000; + lifetimeVarianceMS = 0; + + spinRandomMin = 0.0; + spinRandomMax = 0.0; + windcoefficient = 0; + textureName = "special/BigSpark"; + + colors[0] = "1 1 1.0 1"; + colors[1] = "1 1 1.0 1"; + colors[2] = "1 1 1.0 1"; + colors[3] = "1 1 1.0 0.1"; + + sizes[0] = 0; + sizes[1] = 5; + sizes[2] = 3; + sizes[3] = 0; + + times[0] = 0.0; + times[1] = 0.04; + times[2] = 0.08; + times[3] = 1; + +}; + +datablock ParticleEmitterData(Mpm_B_MIS1_PE2):Mpm_B_MIS_PE1 +{ + lifetimeMS = 10; + ejectionPeriodMS = 50; + periodVarianceMS = 0; + + ejectionVelocity = 5; + velocityVariance = 0.0; + ejectionoffset = 5; + thetaMin = 150.0; + thetaMax = 180.0; + phiReferenceVel = "0"; + phiVariance = "360"; + + orientParticles = true; + orientOnVelocity = true; + + particles = "Mpm_B_MIS1_P2"; +}; + + + +datablock SeekerProjectileData(Mpm_B_MIS1):MpmMissile1 +{ + casingShapeName = "weapon_missile_casement.dts"; + projectileShapeName = "turret_muzzlePoint.dts"; + + + explosion = "GrenadeExplosion"; + splash = MissileSplash; + + baseEmitter = Mpm_B_MIS1_PE1; + delayEmitter = Mpm_B_MIS1_PE2; + puffEmitter = MissilePuffEmitter; + bubbleEmitter = GrenadeBubbleEmitter; + bubbleEmitTime = 1.0; + + exhaustEmitter = MissileLauncherExhaustEmitter; + exhaustTimeMs = 300; + exhaustNodeName = "muzzlePoint1"; + + lifetimeMS = -1; + muzzleVelocity = 0.1; + maxVelocity = 80000; + turningSpeed = 0.0; + acceleration = 3; + scale = "1 1 1"; + proximityRadius = 3; + + terrainAvoidanceSpeed = 180; + terrainScanAhead = 25; + terrainHeightFail = 12; + terrainAvoidanceRadius = 100; + + flareDistance = 0; + flareAngle = 0; + + sound = HAPCFlyerThrustSound; + //BomberFlyerThrustSound; + explodeOnDeath = "1"; + hasLight = true; + lightRadius = 10.0; + lightColor = "1 1 0"; + + useFlechette = false; + flechetteDelayMs = 550; + casingDeb = FlechetteDebris; + + explodeOnWaterImpact = true; +}; + + + +//Anti Missile + +datablock ParticleData(Mpm_B_MIS2_P1) +{ + dragCoefficient = 5; + gravityCoefficient = 0; + inheritedVelFactor = 0.0; + constantAcceleration = 0; + lifetimeMS = 30000; + lifetimeVarianceMS = 0; + textureName = "special/sniper00"; + windcoefficient = 0; + colors[0] = "0.6 0.6 0.6 1"; + colors[1] = "0.6 0.6 0.6 1"; + colors[2] = "0.6 0.6 0.6 1"; + colors[3] = "0.2 0.2 0.2 0"; + sizes[0] = 0; + sizes[1] = 5; + sizes[2] = 2; + sizes[3] = 2; + times[0] = 0.0; + times[1] = 0.04; + times[2] = 0.08; + times[3] = 1; + +}; + +datablock ParticleEmitterData(Mpm_B_MIS2_PE1) +{ + lifetimeMS = 10; + ejectionPeriodMS = 10; + periodVarianceMS = 0; + + ejectionVelocity = 0; + velocityVariance = 0.0; + ejectionoffset = 2; + thetaMin = 180.0; + thetaMax = 180.0; + + phiReferenceVel = "0"; + phiVariance = "0"; + orientParticles = true; + orientOnVelocity = false; + + particles = "Mpm_B_MIS2_P1"; +}; + +datablock ParticleData(Mpm_B_MIS2_P2):Mpm_B_MIS_P1 +{ + dragCoeffiecient = 0.0; + gravityCoefficient = 0.0; + inheritedVelFactor = 1.0; + constantAcceleration = 0.0; + lifetimeMS = 500; + lifetimeVarianceMS = 0; + + spinRandomMin = -30.0; + spinRandomMax = 30.0; + windcoefficient = 0.5; + textureName = "special/flare3"; + colors[0] = "1 1 0.0 1"; + colors[1] = "1 1 0.0 1"; + colors[2] = "1 1 0.0 1"; + colors[3] = "1 1 0.0 0.1"; + + sizes[0] = 10; + sizes[1] = 10; + sizes[2] = 10; + sizes[3] = 10; + + times[0] = 0.4; + times[1] = 0.6; + times[2] = 0.8; + times[3] = 1; + +}; + +datablock ParticleEmitterData(Mpm_B_MIS2_PE2):Mpm_B_MIS_PE1 +{ + lifetimeMS = 10; + ejectionPeriodMS = 100; + periodVarianceMS = 0; + + ejectionVelocity = 0.1; + velocityVariance = 0.0; + ejectionoffset = 0; + thetaMin = 0.0; + thetaMax = 0.0; + phiReferenceVel = "0"; + phiVariance = "0"; + + orientParticles = false; + orientOnVelocity = false; + + particles = "Mpm_B_MIS2_P2"; +}; + +datablock SeekerProjectileData(Mpm_B_MIS2):MpmMissile1 +{ + casingShapeName = "weapon_missile_casement.dts"; + projectileShapeName = "turret_muzzlePoint.dts"; + + + explosion = "GrenadeExplosion"; + splash = MissileSplash; + + baseEmitter = Mpm_B_MIS2_PE1; + delayEmitter = Mpm_B_MIS2_PE2; + puffEmitter = MissilePuffEmitter; + bubbleEmitter = GrenadeBubbleEmitter; + bubbleEmitTime = 1.0; + + exhaustEmitter = MissileLauncherExhaustEmitter; + exhaustTimeMs = 300; + exhaustNodeName = "muzzlePoint1"; + + lifetimeMS = -1; + muzzleVelocity = 20.0; + maxVelocity = 20; + turningSpeed = 0.0; + acceleration = 0; + scale = "1 1 1"; + proximityRadius = 3; + + terrainAvoidanceSpeed = 180; + terrainScanAhead = 25; + terrainHeightFail = 12; + terrainAvoidanceRadius = 100; + + flareDistance = 0; + flareAngle = 0; + + sound = HAPCFlyerThrustSound; + //BomberFlyerThrustSound; + explodeOnDeath = "1"; + hasLight = true; + lightRadius = 10.0; + lightColor = "1 0 0"; + + useFlechette = false; + flechetteDelayMs = 550; + casingDeb = FlechetteDebris; + + explodeOnWaterImpact = true; +}; + + + + +//Vehicle Missile + +datablock ParticleData(Mpm_B_MIS3_P1) +{ + dragCoeffiecient = 0.0; + gravityCoefficient = 0.0; + inheritedVelFactor = 0.0; + + lifetimeMS = 60000; + lifetimeVarianceMS = 0; + + spinRandomMin = 0.0; + spinRandomMax = 0.0; + windcoefficient = 0.5; + textureName = "skins/jetflare2"; + + colors[0] = "0.3 0.8 0.6 1"; + colors[1] = "0.3 0.8 0.0 0.9"; + colors[2] = "0.3 0.8 0.6 0.5"; + colors[3] = "0.3 0.8 0.6 0.0"; + + sizes[0] = 5; + sizes[1] = 17; + sizes[2] = 18; + sizes[3] = 20; + + times[0] = 0; + times[1] = 0.25; + times[2] = 0.5; + times[3] = 0.75; + + +}; + +datablock ParticleEmitterData(Mpm_B_MIS3_PE1) +{ + + lifetimeMS = 10; + ejectionPeriodMS = 100; + periodVarianceMS = 0; + + ejectionVelocity = 10.0; + velocityVariance = 1.0; + ejectionoffset = 0; + thetaMin = 0.0; + thetaMax = 5.0; + + + orientParticles = false; + orientOnVelocity = false; + + particles = "Mpm_B_MIS3_P1"; +}; + +datablock ParticleData(Mpm_B_MIS3_P2):Mpm_B_MIS_P1 +{ + dragCoeffiecient = 0.0; + gravityCoefficient = 0.0; + inheritedVelFactor = 1.0; + + lifetimeMS = 1000; + lifetimeVarianceMS = 0; + + spinRandomMin = -160.0; + spinRandomMax = 160.0; + windcoefficient = 0; + textureName = "skins/flaregreen"; + UseInvAlpha = false; + colors[0] = "0.7 0.7 1.0 0.5"; + colors[1] = "0.7 0.7 1.0 0.5"; + colors[2] = "0.7 0.7 1.0 0.5"; + colors[3] = "0.7 0.7 1.0 0.5"; + + sizes[0] = 20; + sizes[1] = 20; + sizes[2] = 20; + sizes[3] = 20; + + times[0] = 0.25; + times[1] = 0.25; + times[2] = 0.25; + times[3] = 1; + +}; + +datablock ParticleEmitterData(Mpm_B_MIS3_PE2):Mpm_B_MIS_PE1 +{ + lifetimeMS = 10; + ejectionPeriodMS = 100; + periodVarianceMS = 0; + + ejectionVelocity = 0.1; + velocityVariance = 0.0; + ejectionoffset = 0; + thetaMin = 0.0; + thetaMax = 0.0; + phiReferenceVel = "0"; + phiVariance = "0"; + + orientParticles = false; + orientOnVelocity = false; + + particles = "Mpm_B_MIS3_P2"; +}; + +datablock SeekerProjectileData(Mpm_B_MIS3):MpmMissile1 +{ + casingShapeName = "weapon_missile_casement.dts"; + projectileShapeName = "turret_muzzlePoint.dts"; + + + explosion = "GrenadeExplosion"; + splash = MissileSplash; + + baseEmitter = Mpm_B_MIS3_PE1; + delayEmitter = Mpm_B_MIS3_PE2; + puffEmitter = MissilePuffEmitter; + bubbleEmitter = GrenadeBubbleEmitter; + bubbleEmitTime = 1.0; + + exhaustEmitter = MissileLauncherExhaustEmitter; + exhaustTimeMs = 300; + exhaustNodeName = "muzzlePoint1"; + + lifetimeMS = -1; + muzzleVelocity = 0.1; + maxVelocity = 80000; + turningSpeed = 0.0; + acceleration = 1; + scale = "1 1 1"; + proximityRadius = 3; + + terrainAvoidanceSpeed = 180; + terrainScanAhead = 25; + terrainHeightFail = 12; + terrainAvoidanceRadius = 100; + + flareDistance = 0; + flareAngle = 0; + + sound = HAPCFlyerThrustSound; + //BomberFlyerThrustSound; + explodeOnDeath = "1"; + hasLight = true; + lightRadius = 10.0; + lightColor = "0 1 0"; + + useFlechette = false; + flechetteDelayMs = 550; + casingDeb = FlechetteDebris; + + explodeOnWaterImpact = true; +}; + + + +//Aid Missile + +datablock ParticleData(Mpm_B_MIS4_P1) +{ + dragCoeffiecient = 0.0; + gravityCoefficient = 0.0; + inheritedVelFactor = 0.0; + + lifetimeMS = 60000; + lifetimeVarianceMS = 0; + + spinRandomMin = 0.0; + spinRandomMax = 0.0; + windcoefficient = 0.5; + textureName = "skins/jetflare2"; + + colors[0] = "0.3 0.3 0.8 1"; + colors[1] = "0.0 0.0 0.8 0.9"; + colors[2] = "0.3 0.3 0.8 0.5"; + colors[3] = "0.3 0.3 0.8 0.0"; + + sizes[0] = 5; + sizes[1] = 17; + sizes[2] = 18; + sizes[3] = 20; + + times[0] = 0; + times[1] = 0.25; + times[2] = 0.5; + times[3] = 0.75; + + +}; + +datablock ParticleEmitterData(Mpm_B_MIS4_PE1) +{ + + lifetimeMS = 10; + ejectionPeriodMS = 50; + periodVarianceMS = 0; + + ejectionVelocity = 10.0; + velocityVariance = 1.0; + ejectionoffset = 0; + thetaMin = 0.0; + thetaMax = 5.0; + + + orientParticles = false; + orientOnVelocity = false; + + particles = "Mpm_B_MIS4_P1"; +}; + +datablock ParticleData(Mpm_B_MIS4_P2):Mpm_B_MIS_P1 +{ + dragCoeffiecient = 0.0; + gravityCoefficient = 0.0; + inheritedVelFactor = 1.0; + + lifetimeMS = 1000; + lifetimeVarianceMS = 0; + + spinRandomMin = -160.0; + spinRandomMax = 160.0; + windcoefficient = 0; + textureName = "skins/flaregreen"; + UseInvAlpha = false; + colors[0] = "0.2 0.2 1.0 0.5"; + colors[1] = "0.2 0.2 1.0 0.5"; + colors[2] = "0.2 0.2 1.0 0.5"; + colors[3] = "0.2 0.2 1.0 0.5"; + + sizes[0] = 20; + sizes[1] = 20; + sizes[2] = 20; + sizes[3] = 20; + + times[0] = 0.25; + times[1] = 0.25; + times[2] = 0.25; + times[3] = 1; + +}; + +datablock ParticleEmitterData(Mpm_B_MIS4_PE2):Mpm_B_MIS_PE1 +{ + lifetimeMS = 10; + ejectionPeriodMS = 100; + periodVarianceMS = 0; + + ejectionVelocity = 0.1; + velocityVariance = 0.0; + ejectionoffset = 0; + thetaMin = 0.0; + thetaMax = 0.0; + phiReferenceVel = "0"; + phiVariance = "0"; + + orientParticles = false; + orientOnVelocity = false; + + particles = "Mpm_B_MIS4_P2"; +}; + +datablock SeekerProjectileData(Mpm_B_MIS4):MpmMissile1 +{ + casingShapeName = "weapon_missile_casement.dts"; + projectileShapeName = "turret_muzzlePoint.dts"; + + + explosion = "GrenadeExplosion"; + splash = MissileSplash; + + baseEmitter = Mpm_B_MIS4_PE1; + delayEmitter = Mpm_B_MIS4_PE2; + puffEmitter = MissilePuffEmitter; + bubbleEmitter = GrenadeBubbleEmitter; + bubbleEmitTime = 1.0; + + exhaustEmitter = MissileLauncherExhaustEmitter; + exhaustTimeMs = 300; + exhaustNodeName = "muzzlePoint1"; + + lifetimeMS = -1; + muzzleVelocity = 0.1; + maxVelocity = 80000; + turningSpeed = 0.0; + acceleration = 1; + scale = "1 1 1"; + proximityRadius = 3; + + terrainAvoidanceSpeed = 180; + terrainScanAhead = 25; + terrainHeightFail = 12; + terrainAvoidanceRadius = 100; + + flareDistance = 0; + flareAngle = 0; + + sound = HAPCFlyerThrustSound; + //BomberFlyerThrustSound; + explodeOnDeath = "1"; + hasLight = true; + lightRadius = 10.0; + lightColor = "0 0 1"; + + useFlechette = false; + flechetteDelayMs = 550; + casingDeb = FlechetteDebris; + + explodeOnWaterImpact = true; +}; + + diff --git a/scripts/MPM/Mpm_TE.cs b/scripts/MPM/Mpm_TE.cs new file mode 100644 index 0000000..3352f04 --- /dev/null +++ b/scripts/MPM/Mpm_TE.cs @@ -0,0 +1,193 @@ +if ($mpm_TE != 1) + { + $mpm_load[$mpm_loads] = Mpm_TE_Load; + $mpm_loads++; + $mpm_TE = 1; + } + + +datablock ItemData(Mpm_TE_Load) +{ + cost = 10; + missile = Mpm_B_MIS; + name = "MPB Telleporter"; + friendly = 1; + slot = 0; +}; + + + +datablock ParticleData(Mpm_TE_P) +{ + dragCoeffiecient = 0.0; + gravityCoefficient = 0.0; + inheritedVelFactor = 0.0; + + lifetimeMS = 1500; + lifetimeVarianceMS = 0; + + spinRandomMin = 30.0; + spinRandomMax = 30.0; + windcoefficient = 0; + textureName = "skins/jetflare03"; + + colors[0] = "0.3 0.3 1.0 0.1"; + colors[1] = "0.3 0.3 1.0 1"; + colors[2] = "0.3 0.3 1.0 1"; + colors[3] = "0.3 0.3 1.0 0.1"; + + sizes[0] = 5; + sizes[1] = 5; + sizes[2] = 5; + sizes[3] = 5; + + times[0] = 0.25; + times[1] = 0.5; + times[2] = 0.75; + times[3] = 1; + +}; + +datablock ParticleEmitterData(Mpm_TE_PE) +{ + lifetimeMS = 10; + ejectionPeriodMS = 10; + periodVarianceMS = 0; + + ejectionVelocity = 0.01; + velocityVariance = 0.0; + ejectionoffset = 8; + thetaMin = 80.0; + thetaMax = 100.0; + + phiReferenceVel = "180"; + phiVariance = "5"; + orientParticles = false; + orientOnVelocity = false; + + particles = "Mpm_TE_P"; +}; + + +function Mpm_TE_Load::Explode(%data,%p,%pos) +{ +//echo("explode"); +if (IsObject(%p)) + { + //if(VectorDist(%p.targetlocation,%pos)<50) + %p.load.AtTarget(%p); + } +} + +function Mpm_TE_Load::AtTarget(%data,%p) +{ +//echo("attar"); +if (IsObject(%p)) + { + %p.source.mpb.MPM_TelleportMpb(VectorAdd(%p.getTransform(),"0 0 10")); + } +} + + +function Mpb_undeploy(%obj) +{ + if (%obj.deploySchedule) + { + %obj.deploySchedule.clear(); + %obj.deploySchedule = ""; + } + + if (%obj.deployed !$= "" && %obj.deployed == 1) + { + %obj.setThreadDir($DeployThread, false); + %obj.playThread($DeployThread,"deploy"); + %obj.playAudio($DeploySound, MobileBaseUndeploySound); + %obj.station.setThreadDir($DeployThread, false); + %obj.station.getDataBlock().onLosePowerDisabled(%obj.station); + %obj.station.clearSelfPowered(); + %obj.station.goingOut=false; + %obj.station.notDeployed = 1; + %obj.station.playAudio($DeploySound, MobileBaseStationUndeploySound); + + if (isObject(%obj.turret) && isObject(%turretClient = %obj.turret.getControllingClient()) !$= "") + { + CommandToServer( 'resetControlObject', %turretClient ); + } + if (isObject(%obj.turret)) + %obj.turret.setThreadDir($DeployThread, false); + //[most] + if (isObject(%obj.nuke)) + %obj.nuke.mpm_all_off(0); + //[most] + %obj.turret.clearTarget(); + %obj.turret.setTargetObject(-1); + + %obj.turret.playAudio($DeploySound, MobileBaseTurretUndeploySound); + %obj.shield.open(); + %obj.shield.schedule(1000,"delete"); + %obj.deploySchedule = ""; + + %obj.fullyDeployed = 0; + + %obj.noEnemyControl = 0; + } + %obj.deployed = 0; + +} + +function GameBase::MPM_TelleportMpb(%mpb,%target) +{ +%p1 = CreateEmitter(%mpb.getTransform(),Mpm_TE_PE); +%p2 = CreateEmitter(%mpb.getTransform(),Mpm_TE_PE); +%p2.setRotation("1 0 0 3.14"); +%p3 = CreateEmitter(%target,Mpm_TE_PE); +%p4 = CreateEmitter(%target,Mpm_TE_PE); +%p4.setRotation("1 0 0 3.14"); +if (%mpb.deployed) + { + if (IsObject(%mpb.nuke.leftpad.getMountedObject(0))) + %mpb.mountObject(%mpb.nuke.leftpad.getMountedObject(0),0); + else if (IsObject(%mpb.nuke.rightpad.getMountedObject(0))) + %mpb.mountObject(%mpb.nuke.rightpad.getMountedObject(0),0); + + %mpb.schedule(7000,"telleport",%target); + Schedule(7000,%mpb,"RadiusTelleport",%mpb,%mpb.getTransform(),%target); + %p1.schedule(11000,"delete"); + %p2.schedule(11000,"delete"); + %p3.schedule(11000,"delete"); + %p4.schedule(11000,"delete"); + mpb_undeploy(%mpb); + } +else + { + %mpb.schedule(1500,"telleport",%target); + Schedule(1500,%mpb,"RadiusTelleport",%mpb,%mpb.getTransform(),%target); + %p1.schedule(5500,"delete"); + %p2.schedule(5500,"delete"); + %p3.schedule(5500,"delete"); + %p4.schedule(5500,"delete"); + } + +} + +function RadiusTelleport(%obj,%pos,%target) +{ +%mask = $TypeMasks::PlayerObjectType | $TypeMasks::ItemObjectType; +InitContainerRadiusSearch(%pos, 8, %mask); +while ((%test = containerSearchNext()) != 0) +{ +if (%test != %obj && %test != %obj.getMountedObject(0)) + { + %offset = VectorSub(%test.getTransform(),%pos); + %test.telleport(VectorAdd(%target,%offset)); + } +} +} + +function GameBase::telleport(%obj,%pos) +{ +teleportStartFX(%obj); +schedule(500,0,"teleportEndFX",%obj); +%obj.schedule(500,"SetTransform",%pos SPC rot(%obj)); +} + diff --git a/scripts/MPM/Mpm_VE.cs b/scripts/MPM/Mpm_VE.cs new file mode 100644 index 0000000..fee65e2 --- /dev/null +++ b/scripts/MPM/Mpm_VE.cs @@ -0,0 +1,205 @@ +if ($mpm_VE!=1) + { + $mpm_load[$mpm_loads] = Mpm_VE_Load0; + $mpm_loads++; + $mpm_load[$mpm_loads] = Mpm_VE_Load1; + $mpm_loads++; + $mpm_load[$mpm_loads] = Mpm_VE_Load2; + $mpm_loads++; + $mpm_load[$mpm_loads] = Mpm_VE_Load3; + $mpm_loads++; + $mpm_load[$mpm_loads] = Mpm_VE_Load4; + $mpm_loads++; + $mpm_load[$mpm_loads] = Mpm_VE_Load5; + $mpm_loads++; + $mpm_load[$mpm_loads] = Mpm_VE_Load6; + $mpm_loads++; + $mpm_load[$mpm_loads] = Mpm_VE_Load7; + $mpm_loads++; + $mpm_load[$mpm_loads] = Mpm_VE_Load8; + $mpm_loads++; + $mpm_VE = 1; + } + +datablock ParticleData(Mpm_VE_P1) +{ + dragCoeffiecient = 0.0; + gravityCoefficient = 0.0; + inheritedVelFactor = 0.0; + + lifetimeMS = 2500; + lifetimeVarianceMS = 0; + + spinRandomMin = 0.0; + spinRandomMax = 0.0; + windcoefficient = 0; + textureName = "special/GameGrid"; + + colors[0] = "0.3 0.3 1.0 0.1"; + colors[1] = "0.3 0.3 1.0 1"; + colors[2] = "0.3 0.3 1.0 1"; + colors[3] = "0.3 0.3 1.0 0.1"; + + sizes[0] = 5; + sizes[1] = 5; + sizes[2] = 5; + sizes[3] = 5; + + times[0] = 0.1; + times[1] = 0.5; + times[2] = 0.9; + times[3] = 1; + +}; + + +datablock ParticleData(Mpm_VE_P2) +{ + dragCoeffiecient = 0.0; + gravityCoefficient = 0.0; + inheritedVelFactor = 0.0; + + lifetimeMS = 2500; + lifetimeVarianceMS = 0; + + spinRandomMin = 0.0; + spinRandomMax = 0.0; + windcoefficient = 0; + textureName = "special/GameGrid"; + + + colors[0] = "0.3 0.3 1.0 0.1"; + colors[1] = "0.3 0.3 1.0 1"; + colors[2] = "0.3 0.3 1.0 1"; + colors[3] = "0.3 0.3 1.0 0.1"; + + sizes[0] = 5; + sizes[1] = 5; + sizes[2] = 5; + sizes[3] = 5; + + times[0] = 0.1; + times[1] = 0.5; + times[2] = 0.9; + times[3] = 1; + + +}; + +datablock ParticleEmitterData(Mpm_VE_PE1) +{ + lifetimeMS = 10; + ejectionPeriodMS = 15; + periodVarianceMS = 0; + + ejectionVelocity = 0.1; + velocityVariance = 0.0; + ejectionoffset = 8; + thetaMin = 70.0; + thetaMax = 70.0; + + phiReferenceVel = "180"; + phiVariance = "5"; + orientParticles = true; + orientOnVelocity = false; + + particles = "Mpm_VE_P1"; +}; + + +datablock ParticleEmitterData(Mpm_VE_PE2) +{ + lifetimeMS = 10; + ejectionPeriodMS = 15; + periodVarianceMS = 0; + + ejectionVelocity = 0.01; + velocityVariance = 0.0; + ejectionoffset = 8; + thetaMin = 30.0; + thetaMax = 30.0; + + phiReferenceVel = "180"; + phiVariance = "5"; + orientParticles = true; + orientOnVelocity = false; + + + particles = "Mpm_VE_P2"; +}; + +datablock ItemData(Mpm_VE_Load0) +{ + cost = 20; + missile = Mpm_B_MIS3; + name = "[Vehicle] Grav Cycle Missile"; + friendly = 1; + vehicle = ScoutVehicle; + slot = 0; +}; + +datablock ItemData(Mpm_VE_Load1):Mpm_VE_Load0 +{ + cost = 40; + name = "[Vehicle] Tank Missile"; + vehicle = AssaultVehicle; +}; +datablock ItemData(Mpm_VE_Load2):Mpm_VE_Load0 +{ + cost = 100; + name = "[Vehicle] Mpb Missile"; + vehicle = MobileBaseVehicle; +}; + +datablock ItemData(Mpm_VE_Load3):Mpm_VE_Load0 +{ + cost = 25; + name = "[Vehicle] Shrike Missile"; + vehicle = ScoutFlyer; +}; +datablock ItemData(Mpm_VE_Load4):Mpm_VE_Load0 +{ + cost = 50; + name = "[Vehicle] Bomber Missile"; + vehicle = BomberFlyer; +}; + +datablock ItemData(Mpm_VE_Load5):Mpm_VE_Load0 +{ + cost = 80; + name = "[Vehicle] Havoc Missile"; + vehicle = HAPCFlyer; +}; +datablock ItemData(Mpm_VE_Load6):Mpm_VE_Load0 +{ + cost = 800; + name = "[Vehicle] Super Grav Cycle Missile"; + vehicle = SuperScoutVehicle; +}; + +datablock ItemData(Mpm_VE_Load7):Mpm_VE_Load0 +{ + cost = 800; + name = "[Vehicle] Super Havoc Missile"; + vehicle = SuperHAPCFlyer; +}; +datablock ItemData(Mpm_VE_Load8):Mpm_VE_Load0 +{ + cost = 700; + name = "[Vehicle] Artillery Missile"; + vehicle = Artillery; +}; + +function Mpm_VE_Load0::AtTarget(%data,%p) +{ +if (IsObject(%p) && vehicleCheck(%p.load.vehicle, %p.source.team)) + { + %p1 = CreateEmitter(%p.getTransform(),Mpm_VE_PE1); + %p2 = CreateEmitter(%p.getTransform(),Mpm_VE_PE2); + $VehicleTotalCount[%p.source.team, %p.load.vehicle]++; + %vehicle = %p.load.vehicle.create(%p.source.team); + %vehicle.telleport(VectorAdd(%p.getTransform(),"0 0 10")); + %p1.schedule(8000,"delete"); + %p2.schedule(8000,"delete"); + } +} diff --git a/scripts/MPM/Nuclear_blast.cs b/scripts/MPM/Nuclear_blast.cs new file mode 100644 index 0000000..02a355d --- /dev/null +++ b/scripts/MPM/Nuclear_blast.cs @@ -0,0 +1,1356 @@ +//-------------------------------------- +// Arrow IV Nuclear Launcher +//-------------------------------------- + +//----------------------------------------- +//----------------------------------------- +//Copyright (C) Dave "Uranium - 235" Schutz +//----------------------------------------- +//----------------------------------------- + + + + +//-------------------------------------------------------------------------- +// Sounds +//-------------------------------------- + +datablock AudioProfile(NuclearSwitchSound) +{ + filename = "fx/weapons/missile_launcher_activate.wav"; + description = AudioClosest3d; + preload = true; + effect = NuclearSwitchEffect; +}; + + +datablock AudioProfile(NuclearProjectileSound) +{ + filename = "fx/weapons/missile_projectile.wav"; + description = ProjectileLooping3d; + preload = true; +}; + +datablock AudioProfile(NuclearReloadSound) +{ + filename = "fx/weapons/weapon.missilereload.wav"; + description = AudioClosest3d; + preload = true; +}; + +datablock AudioProfile(NuclearLockSound) +{ + filename = "fx/weapons/missile_launcher_searching.WAV"; + description = AudioClosest3d; + preload = true; +}; + +datablock AudioProfile(NuclearDryFireSound) +{ + filename = "fx/weapons/missile_launcher_dryfire.wav"; + description = AudioClose3d; + preload = true; + effect = NuclearDryFireEffect; +}; + +datablock AudioProfile(NukeDeathSound) +{ + filename = "voice/derm1/gbl.brag.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(NuclearFireSound) +{ + filename = "fx/weapons/grenade_flash_explode.wav"; + description = AudioDefault3d; + preload = true; + effect = NuclearFireEffect; +}; + +datablock AudioProfile(NuclearExplosionSound) +{ + filename = "fx/vehicles/bomber_bomb_impact.wav"; + description = AudioBIGExplosion3d; + preload = true; + effect = NuclearExplosionEffect; +}; + +//---------------------------------------------------------------------------- +// Explosion smoke particles +//---------------------------------------------------------------------------- + +datablock ParticleData(NuclearSmokeParticle) +{ + dragCoeffiecient = 0.0; + gravityCoefficient = -0.02; + inheritedVelFactor = 0.1; + + lifetimeMS = 8200; + 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.7 0.7 0.7 1.0"; + colors[2] = "0.5 0.5 0.5 0.0"; + sizes[0] = 4; + sizes[1] = 6; + sizes[2] = 8; + times[0] = 0.0; + times[1] = 0.1; + times[2] = 1.0; + +}; + +datablock ParticleEmitterData(NuclearSmokeEmitter) +{ + ejectionPeriodMS = 10; + periodVarianceMS = 0; + + ejectionVelocity = 1.5; + velocityVariance = 0.3; + + thetaMin = 0.0; + thetaMax = 25.0; + + particles = "NuclearSmokeParticle"; +}; + +datablock ParticleData(NuclearFireParticle) +{ + dragCoeffiecient = 0.0; + gravityCoefficient = 0.0; + inheritedVelFactor = 1.0; + + lifetimeMS = 1000; + 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] = 2; + sizes[1] = 4; + sizes[2] = 5.5; + times[0] = 0.0; + times[1] = 0.3; + times[2] = 1.0; +}; + +datablock ParticleEmitterData(NuclearFireEmitter) +{ + ejectionPeriodMS = 15; + periodVarianceMS = 0; + + ejectionVelocity = 15.0; + velocityVariance = 0.0; + + thetaMin = 0.0; + thetaMax = 0.0; + + particles = "NuclearFireParticle"; +}; + +//--------------------------------------------------------------------------- +// Shockwaves +//--------------------------------------------------------------------------- + +datablock ShockwaveData(NuclearShockwave) +{ + width = 5; + numSegments = 20; + numVertSegments = 4; + velocity = 100; + acceleration = -10.0; // was 40 + lifetimeMS = 8200; + height = 2.0; // was 1.0 + verticalCurve = 0.5; + + mapToTerrain = true; + renderBottom = true; + + 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] = "1.0 0.7 0.5 1.0"; + colors[1] = "1.0 0.5 0.2 1.0"; + colors[2] = "1.0 0.25 0.1 0.0"; + +}; + +datablock ShockwaveData(NuclearShockwave2) +{ + width = 20.0; + numSegments = 50; + numVertSegments = 4; + velocity = 350; + acceleration = 0.0; // was 40 + lifetimeMS = 3000; + height = 300.0; // was 1.0 + verticalCurve = 0.5; + + mapToTerrain = false; + orientToNormal = false; + renderBottom = true; + + 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.7 0.7 1.0 1.0"; + colors[1] = "0.7 0.7 1.0 0.5"; + colors[2] = "0.7 0.7 1.0 1.0"; + +}; + +datablock ShockwaveData(NuclearShockwave3) +{ + width = 6.0; + numSegments = 32; + numVertSegments = 60; + velocity = 150; + acceleration = -5.0; + lifetimeMS = 8000; + height = 20.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.8 0.8 0.0 0.50"; + colors[1] = "0.4 0.4 0.0 0.25"; + colors[2] = "0.4 0.4 0.0 0.0"; + + mapToTerrain = true; + orientToNormal = false; + renderBottom = true; +}; + +//-------------------------------------------------------------------------- +// Particle effects +//-------------------------------------- + +//---------------------------------------------------- +//Condensation +//---------------------------------------------------- +datablock ParticleData(NuclearCapSmokeParticle) +{ + dragCoefficient = 0.25; + gravityCoefficient = -0.01; + windCoefficient = 0; + inheritedVelFactor = 0.025; + constantAcceleration = 0; + lifetimeMS = 30000; + lifetimeVarianceMS = 100; + useInvAlpha = 1; + spinRandomMin = -90; + spinRandomMax = 90; + textureName = "particleTest"; + colors[0] = "0.3 0.3 0.3 0.5"; + colors[1] = "0.3 0.3 0.3 0.5"; + colors[2] = "0.3 0.3 0.3 0.0"; + sizes[0] = 50; + sizes[1] = 50; + sizes[2] = 50; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; +}; + +datablock ParticleEmitterData(NuclearCapSmokeEmitter) +{ + ejectionPeriodMS = 1; + periodVarianceMS = 0; + ejectionVelocity = 40.0; + velocityVariance = 5; + ejectionOffset = 0; + thetaMin = 90; + thetaMax = 180; + phiReferenceVel = 0; + phiVariance = 360; + + lifeTimeMS = 5000; + orientParticles = 0; + orientOnVelocity = 1; + particles = "NuclearCapSmokeParticle"; +}; + +datablock ParticleData(NuclearStemSmokeParticle) +{ + dragCoeffiecient = 0.0; + gravityCoefficient = 0.0; + inheritedVelFactor = 0.0; + windcoefficient = 0.0; + + lifetimeMS = 30000; + lifetimeVarianceMS = 100; + + textureName = "particleTest"; + + useInvAlpha = true; + spinRandomMin = -90.0; + spinRandomMax = 90.0; + + colors[0] = "0.3 0.3 0.3 0.5"; + colors[1] = "0.3 0.3 0.3 0.5"; + colors[2] = "0.3 0.3 0.3 0.0"; + sizes[0] = 50; + sizes[1] = 50; + sizes[2] = 50; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; + +}; + +datablock ParticleEmitterData(NuclearStemSmokeEmitter) +{ + ejectionPeriodMS = 10; + periodVarianceMS = 0; + + ejectionVelocity = 2.0; + velocityVariance = 1.0; + + thetaMin = 0.0; + thetaMax = 90.0; + + particles = "NuclearStemSmokeParticle"; +}; + +datablock ParticleData(NuclearDustParticle) +{ + dragCoefficient = 1.0; + gravityCoefficient = 0.00; + windcoefficient = 0.0; + inheritedVelFactor = 0.0; + constantAcceleration = 0.0; + lifetimeMS = 30000; + lifetimeVarianceMS = 100; + useInvAlpha = true; + spinRandomMin = -90.0; + spinRandomMax = 90.0; + textureName = "particleTest"; + + colors[0] = "0.3 0.3 0.3 0.5"; + colors[1] = "0.3 0.3 0.3 0.5"; + colors[2] = "0.3 0.3 0.3 0.0"; + sizes[0] = 50; + sizes[1] = 50; + sizes[2] = 50; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; +}; + +datablock ParticleEmitterData(NuclearDustEmitter) +{ + ejectionPeriodMS = 1; + periodVarianceMS = 0; + ejectionVelocity = 150.0; + velocityVariance = 150.0; + ejectionOffset = 0.0; + thetaMin = 85; + thetaMax = 85; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + lifetimeMS = 3000; + particles = "NuclearDustParticle"; +}; + +datablock ParticleData(LargeCondensationParticle) +{ + dragCoefficient = 1; + gravityCoefficient = 0; + windCoefficient = 0; + inheritedVelFactor = 0; + constantAcceleration = 0; + lifetimeMS = 12000; + lifetimeVarianceMS = 1000; + useInvAlpha = 0; + spinRandomMin = -90; + spinRandomMax = 500; + textureName = "particleTest"; + times[0] = 0; + times[1] = 0.33; + times[2] = 1; + 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] = 30; + sizes[1] = 30; + sizes[2] = 30; +}; + +datablock ParticleEmitterData(LargeCondensationEmitter) +{ + ejectionPeriodMS = 1; + periodVarianceMS = 0; + ejectionVelocity = 2.66935; + velocityVariance = 2.59677; + ejectionOffset = 325; + thetaMin = 90; + thetaMax = 90; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = 0; + lifeTimeMS = 750; + orientParticles= 0; + orientOnVelocity = 0; + particles = "LargeCondensationParticle"; +}; + +datablock ParticleData(SmallCondensationParticle) +{ + dragCoefficient = 1; + gravityCoefficient = -0.01; + windCoefficient = 0; + inheritedVelFactor = 0; + constantAcceleration = 0; + lifetimeMS = 12000; + lifetimeVarianceMS = 1000; + useInvAlpha = 0; + spinRandomMin = -90; + spinRandomMax = 500; + textureName = "particleTest"; + times[0] = 0; + times[1] = 0.5; + times[2] = 1; + 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] = 30; + sizes[1] = 30; + sizes[2] = 30; +}; + +datablock ParticleEmitterData(SmallCondensationEmitter) +{ + ejectionPeriodMS = 1; + periodVarianceMS = 0; + ejectionVelocity = 2.66935; + velocityVariance = 2.59677; + ejectionOffset = 275; + thetaMin = 90; + thetaMax = 90; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = 0; + lifeTimeMS = 750; + orientParticles= 0; + orientOnVelocity = 0; + particles = "SmallCondensationParticle"; +}; + +datablock ParticleData(UpperRingParticle) +{ + dragCoefficient = 1.0; + gravityCoefficient = 0; + windCoefficient = 0; + inheritedVelFactor = 0; + constantAcceleration = 0; + lifetimeMS = 12000; + lifetimeVarianceMS = 1000; + useInvAlpha = 0; + spinRandomMin = -90; + spinRandomMax = 500; + textureName = "particleTest"; + times[0] = 0; + times[1] = 0.5; + times[2] = 1; + 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] = 30; + sizes[1] = 30; + sizes[2] = 30; +}; + +datablock ParticleEmitterData(UpperRingEmitter) +{ + ejectionPeriodMS = 1; + periodVarianceMS = 0; + ejectionVelocity = 50; + velocityVariance = 50; + ejectionOffset = 150; + thetaMin = 90; + thetaMax = 90; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = 0; + lifeTimeMS = 8000; + orientParticles= 0; + orientOnVelocity = 1; + particles = "UpperRingParticle"; +}; + +datablock ParticleData(NuclearSplashParticle) +{ + dragCoefficient = 0; + gravityCoefficient = 0.1; + windCoefficient = 0; + inheritedVelFactor = 0; + constantAcceleration = 0; + lifetimeMS = 10000; + lifetimeVarianceMS = 1000; + useInvAlpha = 0; + spinRandomMin = 0; + spinRandomMax = 0; + textureName = "special/droplet"; + times[0] = 0; + times[1] = 0.5; + times[2] = 1; + 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] = 4.74194; + sizes[1] = 4.74194; + sizes[2] = 4.74194; +}; + +datablock ParticleEmitterData(NuclearSplashEmitter) +{ + ejectionPeriodMS = 1; + periodVarianceMS = 0; + ejectionVelocity = 10; + velocityVariance = 10; + ejectionOffset = 10; + thetaMin = 0; + thetaMax = 31.2097; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = 0; + lifeTimeMS = 10000; + orientParticles= 1; + orientOnVelocity = 1; + particles = "NuclearSplashParticle"; +}; + +datablock ParticleData(DomeCondensationParticle) +{ + dragCoefficient = 0.1; + gravityCoefficient = 0; + windCoefficient = 0; + inheritedVelFactor = 0; + constantAcceleration = 0; + lifetimeMS = 15000; + lifetimeVarianceMS = 0; + useInvAlpha = 0; + spinRandomMin = -90; + spinRandomMax = 500; + textureName = "particleTest"; + times[0] = 0; + times[1] = 0.5; + times[2] = 1; + 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] = 7; + sizes[1] = 7; + sizes[2] = 7; +}; + +datablock ParticleEmitterData(DomeCondensationEmitter) +{ + ejectionPeriodMS = 1; + periodVarianceMS = 0; + ejectionVelocity = 10; + velocityVariance = 1; + ejectionOffset = 10; + thetaMin = 90; + thetaMax = 0; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = 0; + lifeTimeMS = 3000; + orientParticles= 0; + orientOnVelocity = 1; + particles = "DomeCondensationParticle"; +}; + +// More explosions + +datablock ExplosionData(RingExplosion1) +{ + emitter[0] = SmallCondensationEmitter; + + shakeCamera = true; + camShakeFreq = "10.0 11.0 10.0"; + camShakeAmp = "20.0 20.0 20.0"; + camShakeDuration = 0.5; + camShakeRadius = 10.0; + + sizes[0] = "0.01 0.01 0.01"; + sizes[1] = "0.01 0.01 0.01"; + times[0] = 0.0; + times[1] = 1.0; +}; + +datablock ExplosionData(RingExplosion2) +{ + emitter[0] = LargeCondensationEmitter; + + shakeCamera = true; + camShakeFreq = "10.0 11.0 10.0"; + camShakeAmp = "20.0 20.0 20.0"; + camShakeDuration = 0.5; + camShakeRadius = 10.0; + + sizes[0] = "0.01 0.01 0.01"; + sizes[1] = "0.01 0.01 0.01"; + times[0] = 0.0; + times[1] = 1.0; +}; + +datablock ExplosionData(UpperRingExplosion) +{ + emitter[0] = UpperRingEmitter; + + shakeCamera = true; + camShakeFreq = "10.0 11.0 10.0"; + camShakeAmp = "20.0 20.0 20.0"; + camShakeDuration = 0.5; + camShakeRadius = 10.0; + + sizes[0] = "0.01 0.01 0.01"; + sizes[1] = "0.01 0.01 0.01"; + times[0] = 0.0; + times[1] = 1.0; +}; + +datablock ExplosionData(DustExplosion) +{ + emitter[0] = NuclearDustEmitter; + + shakeCamera = true; + camShakeFreq = "10.0 11.0 10.0"; + camShakeAmp = "20.0 20.0 20.0"; + camShakeDuration = 0.5; + camShakeRadius = 10.0; + + sizes[0] = "0.01 0.01 0.01"; + sizes[1] = "0.01 0.01 0.01"; + times[0] = 0.0; + times[1] = 1.0; +}; + +datablock ExplosionData(CapExplosion) +{ + emitter[0] = NuclearCapSmokeEmitter; + + shakeCamera = true; + camShakeFreq = "10.0 11.0 10.0"; + camShakeAmp = "20.0 20.0 20.0"; + camShakeDuration = 0.5; + camShakeRadius = 10.0; + + sizes[0] = "0.01 0.01 0.01"; + sizes[1] = "0.01 0.01 0.01"; + times[0] = 0.0; + times[1] = 1.0; +}; + +datablock ExplosionData(NuclearSplash) +{ + emitter[0] = NuclearSplashEmitter; + + shakeCamera = true; + camShakeFreq = "10.0 11.0 10.0"; + camShakeAmp = "20.0 20.0 20.0"; + camShakeDuration = 0.5; + camShakeRadius = 10.0; + + sizes[0] = "0.01 0.01 0.01"; + sizes[1] = "0.01 0.01 0.01"; + times[0] = 0.0; + times[1] = 1.0; +}; + +datablock ExplosionData(DomeCondensationExplosion) +{ + emitter[0] = DomeCondensationEmitter; + + shakeCamera = true; + camShakeFreq = "10.0 11.0 10.0"; + camShakeAmp = "20.0 20.0 20.0"; + camShakeDuration = 0.5; + camShakeRadius = 10.0; + + sizes[0] = "0.01 0.01 0.01"; + sizes[1] = "0.01 0.01 0.01"; + times[0] = 0.0; + times[1] = 1.0; +}; + + +//--------------------------------------------------------------------------- +// Explosions +//--------------------------------------------------------------------------- +datablock ExplosionData(NuclearExplosion1) +{ + shockwave = NuclearShockwave2; + shockwaveOnTerrain = false; + + explosionShape = "effect_plasma_explosion.dts"; + + playSpeed = 0.05; + soundProfile = NuclearExplosionSound; + faceViewer = true; + + sizes[0] = "100.0 100.0 100.0"; + + shakeCamera = true; + camShakeFreq = "6.0 7.0 7.0"; + camShakeAmp = "100.0 100.0 100.0"; + camShakeDuration = 1.0; + camShakeRadius = 7.0; +}; + +datablock ExplosionData(NuclearExplosion2) +{ + shockwave = NuclearShockwave; + shockwaveOnTerrain = false; + + explosionShape = "effect_plasma_explosion.dts"; + + playSpeed = 0.05; + soundProfile = NuclearExplosionSound; + faceViewer = true; + + sizes[0] = "100.0 100.0 100.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(NuclearExplosion3) +{ + explosionShape = "effect_plasma_explosion.dts"; + + playSpeed = 0.05; + soundProfile = NuclearExplosionSound; + faceViewer = true; + + shockwave = NuclearShockwave3; + shockwaveOnTerrain = false; + + sizes[0] = "150.0 150.0 150.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(NuclearExplosion4) +{ + explosionShape = "effect_plasma_explosion.dts"; + + playSpeed = 0.05; + soundProfile = NuclearExplosionSound; + faceViewer = true; + + sizes[0] = "250.0 250.0 250.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(NuclearMainExplosion) +{ + soundProfile = NuclearExplosionSound; + + subExplosion[0] = NuclearExplosion1; + subExplosion[1] = NuclearExplosion2; + subExplosion[2] = NuclearExplosion3; + subExplosion[3] = NuclearExplosion4; + subExplosion[4] = DustExplosion; +}; + +//-------------------------------------------------------------------------- +// Projectile +//-------------------------------------- +datablock SeekerProjectileData(ShoulderNuclear) +{ + casingShapeName = "weapon_missile_casement.dts"; + projectileShapeName = "weapon_missile_projectile.dts"; + hasDamageRadius = true; + indirectDamage = 1000.0; + damageRadius = 250.0; + radiusDamageType = $DamageType::Missile; + kickBackStrength = 100000; + + Underwaterexplosion = "NuclearSplash"; + splash = BlasterSplash; + velInheritFactor = 0.5; + depthTolerance = 10.0; // depth at which it uses underwater explosion + + baseEmitter = NuclearSmokeEmitter; + delayEmitter = NuclearFireEmitter; + puffEmitter = NuclearPuffEmitter; + bubbleEmitter = GrenadeBubbleEmitter; + bubbleEmitTime = 1.0; + + + exhaustEmitter = NuclearExhaustEmitter; + exhaustTimeMs = 2000; + exhaustNodeName = "muzzlePoint1"; + + lifetimeMS = 1800000; //60000 + muzzleVelocity = 1.0; //1 + maxVelocity = 100.0; //80 100 + turningSpeed = 120.0; //110 120 + acceleration = 10.0; //200 10 + + proximityRadius = 5; + + terrainAvoidanceSpeed = 480; //180 + terrainScanAhead = 25; //25 + terrainHeightFail = 3; //12 + terrainAvoidanceRadius = 100; //100 + + flareDistance = 50; //200 + flareAngle = 5; //30 + + sound = NuclearProjectileSound; + + hasLight = true; + lightRadius = 5.0; + lightColor = "0.2 0.05 0"; + + useFlechette = true; + flechetteDelayMs = 550; + casingDeb = FlechetteDebris; + + explodeOnWaterImpact = false; +}; + +datablock LinearProjectileData(RingProjectile1) +{ + projectileShapeName = "weapon_missile_Projectile.dts"; + emitterDelay = -1; + directDamage = 0.0; + hasDamageRadius = true; + indirectDamage = 1.0; + damageRadius = 500.0; + radiusDamageType = $DamageType::EMP; + kickBackStrength = 0; + + sound = discProjectileSound; + explosion = "RingExplosion1"; + underwaterExplosion = "RingExplosion1"; + splash = DiscSplash; + + dryVelocity = 180; + wetVelocity = 180; + velInheritFactor = 0.5; + fizzleTimeMS = 1500; + lifetimeMS = 1500; + explodeOnDeath = true; + reflectOnWaterImpactAngle = 15.0; + explodeOnWaterImpact = true; + deflectionOnWaterImpact = 0.0; + fizzleUnderwaterMS = 5000; + + activateDelayMS = -1; +}; + +datablock LinearProjectileData(RingProjectile2) +{ + projectileShapeName = "weapon_missile_Projectile.dts"; + emitterDelay = -1; + directDamage = 0.0; + hasDamageRadius = true; + indirectDamage = 1000.0; + damageRadius = 250.0; + radiusDamageType = $DamageType::Nuclear; + kickBackStrength = 0; + + sound = discProjectileSound; + explosion = "RingExplosion2"; + underwaterExplosion = "RingExplosion2"; + splash = DiscSplash; + depthTolerance = 10.0; // depth at which it uses underwater explosion + + dryVelocity = 180; + wetVelocity = 180; + velInheritFactor = 0.5; + fizzleTimeMS = 1000; + lifetimeMS = 1000; + explodeOnDeath = true; + reflectOnWaterImpactAngle = 15.0; + explodeOnWaterImpact = true; + deflectionOnWaterImpact = 0.0; + fizzleUnderwaterMS = 5000; + + activateDelayMS = 200; +}; + +datablock LinearProjectileData(StemProjectile1) +{ + projectileShapeName = "weapon_missile_Projectile.dts"; + emitterDelay = 1; + directDamage = 0.0; + hasDamageRadius = true; + indirectDamage = 1000.0; + damageRadius = 250.0; + radiusDamageType = $DamageType::Nuclear; + kickBackStrength = 0; + + baseEmitter = NuclearStemSmokeEmitter; + + dryVelocity = 50; + wetVelocity = 50; + velInheritFactor = 0.5; + fizzleTimeMS = 5000; + lifetimeMS = 5000; + explodeOnDeath = true; + reflectOnWaterImpactAngle = 15.0; + explodeOnWaterImpact = true; + deflectionOnWaterImpact = 0.0; + fizzleUnderwaterMS = 5000; + + activateDelayMS = 200; +}; + +datablock LinearProjectileData(StemProjectile2) +{ + projectileShapeName = "weapon_missile_Projectile.dts"; + emitterDelay = 1; + directDamage = 0.0; + hasDamageRadius = true; + indirectDamage = 1000.0; + damageRadius = 250.0; + radiusDamageType = $DamageType::Nuclear; + kickBackStrength = 0; + + explosion = "CapExplosion"; + underwaterExplosion = "CapExplosion"; + + dryVelocity = 50; + wetVelocity = 50; + velInheritFactor = 0.5; + fizzleTimeMS = 4000; + lifetimeMS = 4000; + explodeOnDeath = true; + reflectOnWaterImpactAngle = 15.0; + explodeOnWaterImpact = true; + deflectionOnWaterImpact = 0.0; + fizzleUnderwaterMS = 4000; + + activateDelayMS = 200; +}; + +datablock LinearProjectileData(UpperRingProjectile1) +{ + projectileShapeName = "weapon_missile_Projectile.dts"; + emitterDelay = 1; + directDamage = 0.0; + hasDamageRadius = true; + indirectDamage = 1000.0; + damageRadius = 250.0; + radiusDamageType = $DamageType::Nuclear; + kickBackStrength = 0; + + explosion = "UpperRingExplosion"; + underwaterExplosion = "UpperRingExplosion"; + + dryVelocity = 180; + wetVelocity = 180; + velInheritFactor = 0.5; + fizzleTimeMS = 2000; + lifetimeMS = 2000; + explodeOnDeath = true; + reflectOnWaterImpactAngle = 15.0; + explodeOnWaterImpact = true; + deflectionOnWaterImpact = 0.0; + fizzleUnderwaterMS = 2000; + + activateDelayMS = -1; +}; + +datablock LinearProjectileData(DustProjectile1) +{ + projectileShapeName = "weapon_missile_Projectile.dts"; + emitterDelay = -1; + directDamage = 0.0; + hasDamageRadius = true; + indirectDamage = 1000.0; + damageRadius = 250.0; + radiusDamageType = $DamageType::Nuclear; + kickBackStrength = 35000; + + maxWhiteout = 2.0; + + sound = discProjectileSound; + explosion = "NuclearMainExplosion"; + underwaterExplosion = "NuclearMainExplosion"; + splash = DiscSplash; + + dryVelocity = 180; + wetVelocity = 180; + velInheritFactor = 0.5; + fizzleTimeMS = 100; + lifetimeMS = 100; + explodeOnDeath = true; + reflectOnWaterImpactAngle = 15.0; + explodeOnWaterImpact = true; + deflectionOnWaterImpact = 0.0; + fizzleUnderwaterMS = 5000; + + activateDelayMS = 200; +}; + +//-------------------------------------------------------------------------- +// Ammo +//-------------------------------------- + +datablock ItemData(NuclearAmmo) +{ + className = Ammo; + catagory = "Ammo"; + shapeFile = "ammo_missile.dts"; + mass = 5; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 2; + pickUpName = "an Arrow IV nuclear missile"; + + computeCRC = true; + +}; + +//-------------------------------------------------------------------------- +// Weapon +//-------------------------------------- +datablock ItemData(Nuclear) +{ + className = Weapon; + catagory = "Spawn Items"; + shapeFile = "turret_tank_barrelmortar.dts"; + image = NuclearImage; + mass = 50; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 2; + pickUpName = "an Arrow IV nuclear launch platform"; + + computeCRC = true; + emap = true; +}; + +datablock ShapeBaseImageData(NuclearImage) +{ + className = WeaponImage; + shapeFile = "turret_missile_large.dts"; + item = Nuclear; + offset = "0.2 0.5 0"; + armThread = lookms; + emap = true; + + usesenergy = true; + minenergy = 0; + + projectile = ShoulderNuclear; + projectileType = SeekerProjectile; + + isSeeker = true; + seekRadius = 100000; + maxSeekAngle = 25; + seekTime = 1.0; + minSeekHeat = 0.5; // the heat that must be present on a target to lock it. + + // only target objects outside this range + minTargetingDistance = 2; + + stateName[0] = "Activate"; + stateTransitionOnTimeout[0] = "ActivateReady"; + stateTimeoutValue[0] = 0.5; + stateSequence[0] = "Activate"; + stateSound[0] = NuclearSwitchSound; + + stateName[1] = "ActivateReady"; + stateTransitionOnLoaded[1] = "Ready"; + stateTransitionOnNoAmmo[1] = "NoAmmo"; + stateSound[1] = NuclearIdleSound; + + stateName[2] = "Ready"; + stateTransitionOnNoAmmo[2] = "NoAmmo"; + stateTransitionOnTriggerDown[2] = "CheckWet"; + + stateName[3] = "Fire"; + stateTransitionOnTimeout[3] = "Reload"; + stateTimeoutValue[3] = 1.5; + stateFire[3] = true; + stateRecoil[3] = LightRecoil; + stateAllowImageChange[3] = false; + stateSequence[3] = "Fire"; + stateScript[3] = "onFire"; + stateSound[3] = NuclearFireSound; + + stateName[4] = "Reload"; + stateTransitionOnNoAmmo[4] = "NoAmmo"; + stateTransitionOnTimeout[4] = "Ready"; + stateTimeoutValue[4] = 0.75; + stateAllowImageChange[4] = false; + stateSequence[4] = "Reload"; + stateSound[4] = NuclearReloadSound; + + stateName[5] = "NoAmmo"; + stateTransitionOnAmmo[5] = "Reload"; + stateSequence[5] = "NoAmmo"; + stateTransitionOnTriggerDown[5] = "DryFire"; + + stateName[6] = "DryFire"; + stateSound[6] = NuclearDryFireSound; + stateTimeoutValue[6] = 1.0; + stateTransitionOnTimeout[6] = "ActivateReady"; + + stateName[7] = "CheckTarget"; + stateTransitionOnNoTarget[7] = "Fire"; + stateTransitionOnTarget[7] = "Fire"; + + stateName[8] = "CheckWet"; + stateTransitionOnWet[8] = "WetFire"; + stateTransitionOnNotWet[8] = "CheckTarget"; + + stateName[9] = "WetFire"; + stateTransitionOnNoAmmo[9] = "NoAmmo"; + stateTransitionOnTimeout[9] = "Reload"; + stateSound[9] = NuclearFireSound; + stateRecoil[3] = LightRecoil; + stateTimeoutValue[9] = 0.25; + stateSequence[3] = "Fire"; + stateScript[9] = "onWetFire"; + stateAllowImageChange[9] = false; +}; + +function ShoulderNuclear::onExplode(%data, %proj, %pos, %mod) +{ + if (%data.hasDamageRadius) + RadiusExplosion(%proj, %pos, %data.damageRadius, %data.indirectDamage, %data.kickBackStrength, %proj.sourceObject, %data.radiusDamageType); + for(%i=0;%i<1;%i++) + { + %p = new LinearProjectile() { + dataBlock = RingProjectile2; + initialDirection = "0 0 1"; + initialPosition = %pos; + //sourceObject = %projectile.sourceObject; + sourceSlot = %projectile.sourceSlot; + vehicleObject = %projectile.vehicleObject; + }; + MissionCleanup.add(%p); + } + %p = new LinearProjectile() { + dataBlock = RingProjectile1; + initialDirection = "0 0 1"; + initialPosition = %pos; + //sourceObject = %projectile.sourceObject; + sourceSlot = %projectile.sourceSlot; + vehicleObject = %projectile.vehicleObject; + }; + MissionCleanup.add(%p); + + %p = new LinearProjectile() { + dataBlock = DustProjectile1; + initialDirection = "0 0 1"; + initialPosition = %pos; + //sourceObject = %projectile.sourceObject; + sourceSlot = %projectile.sourceSlot; + vehicleObject = %projectile.vehicleObject; + }; + MissionCleanup.add(%p); + + %p = new LinearProjectile() { + dataBlock = StemProjectile1; + initialDirection = "0 0 1"; + initialPosition = %pos; + //sourceObject = %projectile.sourceObject; + sourceSlot = %projectile.sourceSlot; + vehicleObject = %projectile.vehicleObject; + }; + MissionCleanup.add(%p); + + %p = new LinearProjectile() { + dataBlock = UpperRingProjectile1; + initialDirection = "0 0 1"; + initialPosition = %pos; + //sourceObject = %projectile.sourceObject; + sourceSlot = %projectile.sourceSlot; + vehicleObject = %projectile.vehicleObject; + }; + MissionCleanup.add(%p); + + %p = new LinearProjectile() { + dataBlock = StemProjectile2; + initialDirection = "0 0 1"; + initialPosition = %pos; + //sourceObject = %projectile.sourceObject; + sourceSlot = %projectile.sourceSlot; + vehicleObject = %projectile.vehicleObject; + }; + MissionCleanup.add(%p); + +} + +datablock ShapeBaseImageData(NuclearImage1) +{ + shapeFile = "stackable1m.dts"; + offset = "1.0 1.0 0.5"; + rotation = "90 90 1 90"; +}; + +datablock ShapeBaseImageData(NuclearImage2) +{ + shapeFile = "turret_missile_large.dts"; + offset = "0.2 2.0 0"; + rotation = "0 0 0 0"; +}; + +datablock ShapeBaseImageData(NuclearImage3) +{ + shapeFile = "weapon_targeting.dts"; + offset = "-0.15 0.1 0.0"; + rotation = "0 100 0 1"; +}; + +datablock ShapeBaseImageData(NuclearImage4) +{ + shapeFile = "turret_tank_barrelmortar.dts"; + offset = "0.2 0 0"; + rotation = "0 0 0 0"; +}; + +datablock TargetProjectileData(LaserTargeter) +{ + directDamage = 0.0; + hasDamageRadius = false; + indirectDamage = 0.0; + damageRadius = 0.0; + velInheritFactor = 1.0; + + maxRifleRange = 10000; + beamColor = "0.6 0.0 0.0"; + + startBeamWidth = 0.05; + pulseBeamWidth = 0.025; + beamFlareAngle = 0.0; + minFlareSize = 0.0; + maxFlareSize = 0.0; + pulseSpeed = 1.0; + pulseLength = 0.150; + + textureName[0] = "special/nonlingradient"; + textureName[1] = "special/flare"; + textureName[2] = "special/pulse"; + textureName[3] = "special/generic_scorch"; + beacon = false; +}; + +function NuclearImage::onMount(%this,%obj,%slot) +{ + Parent::onMount(%data,%obj,%slot); + + %obj.mountImage(NuclearImage1,4); + %obj.mountImage(NuclearImage2,5); + %obj.mountImage(NuclearImage3,6); + %obj.mountImage(NuclearImage4,7); + + %mVec = %obj.getMuzzleVector(0); + %mPos = %obj.getMuzzlePoint(0); + %nmVec = VectorNormalize(%mVec); + %scmVec = VectorScale(%nmVec, 1000); + %mEnd = VectorAdd(%mPos, %scmVec); + %searchResult = containerRayCast(%mPos, %mEnd, $TypeMasks::TerrainObjectType | $TypeMasks::InteriorObjectType | $TypeMasks::PlayerObjectType | $TypeMasks::VehicleObjectType | $TypeMasks::StaticShapeObjectType | $TypeMasks::TurretObjectType | $TypeMasks::ItemObjectType, 1); + %raycastPt = posFrRaycast(%searchResult); + + CommandToClient(%obj.client, 'BottomPrint', ">>>Arrow IV Nuclear Launch Platform<<<\nPerfect for flexing your administrative might.\nIt's a nuke. Need we say more? (Blast: 250-300 meters)", 3, 3 ); + + //%obj.setImageLoaded(1, true); + %t = new TargetProjectile() { + dataBlock = "LaserTargeter"; + initialDirection = %obj.getMuzzleVector(%slot); + initialPosition = %obj.getMuzzlePoint(%slot); + sourceObject = %obj; + sourceSlot = 6; + vehicleObject = 0; + }; + MissionCleanup.add(%t); + %obj.t = %t; +} + +function NuclearImage::onUnMount(%this,%obj,%slot) +{ + if(isObject(%obj.t)) + %obj.t.delete(); + + Parent::onunMount(%this,%obj,%slot); + %obj.unmountImage(4); + %obj.unmountImage(5); + %obj.unmountImage(6); + %obj.unmountImage(7); +} + +function GameConnection::GiveNuclear(%cl) +{ +%cl.player.MountImage(Nuclearimage,0); +} + +function NuclearImage::onFire(%data,%obj,%slot) // ADDED HERE +{ + %p = Parent::onFire(%data, %obj, %slot); + MissileSet.add(%p); + + %target = %obj.getLockedTarget(); + if(%target) + %p.setObjectTarget(%target); + else if(%obj.isLocked()) + %p.setPositionTarget(%obj.getLockedPosition()); + else + %p.setNoTarget(); +} + +function NuclearImage::onWetFire(%data, %obj, %slot) +{ + %p = Parent::onFire(%data, %obj, %slot); + MissileSet.add(%p); + + %target = %obj.getLockedTarget(); + if(%target) + %p.setObjectTarget(%target); + else if(%obj.isLocked()) + %p.setPositionTarget(%obj.getLockedPosition()); + else + %p.setNoTarget(); +} diff --git a/scripts/MPM/Nuke_Cannon.cs b/scripts/MPM/Nuke_Cannon.cs new file mode 100644 index 0000000..c3ffbaa --- /dev/null +++ b/scripts/MPM/Nuke_Cannon.cs @@ -0,0 +1,2585 @@ +/////////////////////////////////////////////////////////////////////////////// +// "Project Uber: Planetary Cannon Edition" // +// "The nuke to end all nukes" // +// coded by: Drain Bramage // +//---------------------------------------------------------------------------// +//credit to: HellNight, Lt Earthworm, Southtown, and most expecialy The_Force// // +// also credit to the AdvancedMod coding forums // +//---------------------------------------------------------------------------// +//Features: // +//This nuke is roughly 1000m tall and 150-200m across. It has most of the // +//features of an accualy atomic bomb: The mushroom cloud, impact smoke, smoke// +//ring, debris, shockwaves and compression rings. If you have Burn Damage in// +//your mod this nuke will set stuff on fire.(want the Burn Damage?, look // +//for it at http://www.advancedmod.com/forums/index.php) There is also a // +//warning message and 1 minute countdown displayed in the chat hud, complete // +//with sounds, when this sucker is fired. Lastly there is "ash" that falls // +//over the entire map for 20 seconds after the final explosion. // +//---------------------------------------------------------------------------// +//***New Weapon Image on its way*** ***Maybe a cleaned up version*** // +//---------------------------------------------------------------------------// +//Notes: // +//-Right now the nuke is set up for testing settings, and is very weak // +// for its size, feel free to adjust damage amounts and damage radii to your // +// likeing. // +// // +//-I left several unused particles and emitters and a 2nd "debris" // +//projectile with its onExplode for anyone that might want to use them. // +// // +//-Use the nuke how ever you like but please give credit where its due. // +// // +//-This nuke LAGS, it was not made to be spammed, infact, more than one going // +//off in a semi-full server will probaly crash the server, if it doesnt crash // +//it most of the players will probaly leave due to the lag. This nuke was // +//made for "eyecandy" lovers like myself. // +//----------------------------------------------------------------------------// +//***!!!IMPORTANT!!!*** // +//-You will need to create new audio descriptions for the sounds to work. // +//It is very easy to do, simply open up serverAudio.cs, copy the // +//AudioBIGExplosion3d decription, change the name to AudioNukeUpProjectile3d // +//and AudioNukeTopExplosion3d adjust the settings. I sugest a maximum of // +//between 1000 and 2000 and a minimum of around half your maximum. // +// // +//-The whiteout will not work unless u have function raidusWhiteout. // +//I will not include this function in this file because i do not have permission +//from The_Force to give it out. I'm also to lazy to ask. Go to // +//http://www.advancedmod.com/forums/index.php and find it yourself. // +//----------------------------------------------------------------------------// +//And that concludes all the technical crap, I wrote all that because its 3 in// +//the morning and I'm bored off my ass. I hope you enjoy "Project Uber" // +//because it took me a period of around 36 hours over 3 days. Plus what ever // +//time it takes me to make the weapon image.(work for tomarrow) // +// -Drain Bramage // +//////////////////////////////////////////////////////////////////////////////// +datablock AudioProfile(NukeExplosionSound) +{ + filename = "fx/Bonuses/upward_passback1_bomb.wav"; + description = AudioBIGExplosion3d; + preload = true; +}; + +datablock AudioProfile(NukeBottomExplosionSound) +{ + filename = "fx/explosions/vehicle_explosion.wav"; + description = AudioBIGExplosion3d; + preload = true; +}; + +datablock AudioProfile(NukeTopExplosionSound) +{ + filename = "fx/vehicles/bomber_bomb_impact.wav"; + description = AudioNukeTopExplosion3d; + preload = true; +}; + +datablock AudioProfile(NukeUpProjectileSound) +{ + filename = "fx/vehicles/htransport_boost.wav"; + description = AudioUpProjectile3d; +}; + +datablock AudioProfile(NukeFireSound) +{ + filename = "fx/vehicles/tank_mortar_fire.wav"; + description = AudioClosest3d; +}; + +datablock AudioProfile(NukeReloadSound) +{ + filename = "fx/vehicles/bomber_turret_activate.wav"; + description = AudioClosest3d; +}; +datablock AudioProfile(NukeSwitchSound) +{ + filename = "fx/misc/cannonstart.wav"; + description = AudioBIGExplosion3d; +}; +//nuke explosion emitter +datablock ParticleData(NukeExplosionParticle) +{ + dragCoefficient = 2; + gravityCoefficient = 0.2; + inheritedVelFactor = 0.2; + constantAcceleration = 0.0; + lifetimeMS = 10000; + lifetimeVarianceMS = 150; + useInvAlpha = true; + textureName = "particleTest"; + colors[0] = "0.1 0.1 0.1 1.0"; + colors[1] = "0.1 0.1 0.1 0.3"; + sizes[0] = 0.5; + sizes[1] = 2; +}; + +datablock ParticleEmitterData(NukeExplosionEmitter) +{ + ejectionPeriodMS = 7; + periodVarianceMS = 0; + ejectionVelocity = 100; + velocityVariance = 1.0; + ejectionOffset = 0.0; + thetaMin = 0; + thetaMax = 60; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + particles = "NukeExplosionParticle"; +}; + +//nuke debris +//-------------------------------------------------------------- +// Nuke Debris Fire Particles +//-------------------------------------------------------------- + +datablock ParticleData(NukeDebrisFireParticle) +{ + dragCoeffiecient = 0.0; + gravityCoefficient = -0.2; + inheritedVelFactor = 0.0; + + lifetimeMS = 350; + lifetimeVarianceMS = 0; + + textureName = "particleTest"; + + useInvAlpha = false; + spinRandomMin = -160.0; + spinRandomMax = 160.0; + + animateTexture = true; + framesPerSec = 15; + + + animTexName[0] = "special/Explosion/exp_0016"; + animTexName[1] = "special/Explosion/exp_0018"; + animTexName[2] = "special/Explosion/exp_0020"; + animTexName[3] = "special/Explosion/exp_0022"; + animTexName[4] = "special/Explosion/exp_0024"; + animTexName[5] = "special/Explosion/exp_0026"; + animTexName[6] = "special/Explosion/exp_0028"; + animTexName[7] = "special/Explosion/exp_0030"; + animTexName[8] = "special/Explosion/exp_0032"; + + colors[0] = "1.0 0.7 0.5 1.0"; + colors[1] = "1.0 0.5 0.2 1.0"; + colors[2] = "1.0 0.25 0.1 0.0"; + sizes[0] = 0.5; + sizes[1] = 2.0; + sizes[2] = 1.0; + times[0] = 0.0; + times[1] = 0.2; + times[2] = 1.0; +}; + +datablock ParticleEmitterData(NukeDebrisFireEmitter) +{ + ejectionPeriodMS = 20; + periodVarianceMS = 1; + + ejectionVelocity = 0.25; + velocityVariance = 0.0; + + thetaMin = 0.0; + thetaMax = 30.0; + + particles = "NukeDebrisFireParticle"; +}; +//-------------------------------------------------------------- +// Nuke Debris Smoke Particles +//-------------------------------------------------------------- + +datablock ParticleData( NukeDebrisSmokeParticle ) +{ + dragCoeffiecient = 4.0; + gravityCoefficient = -0.00; // rises slowly + inheritedVelFactor = 0.2; + + lifetimeMS = 1000; + lifetimeVarianceMS = 100; // ...more or less + + textureName = "particleTest"; + + useInvAlpha = true; + + spinRandomMin = -50.0; + spinRandomMax = 50.0; + + colors[0] = "0.3 0.3 0.3 0.0"; + colors[1] = "0.3 0.3 0.3 1.0"; + colors[2] = "0.0 0.0 0.0 0.0"; + sizes[0] = 2; + sizes[1] = 3; + sizes[2] = 5; + times[0] = 0.0; + times[1] = 0.7; + times[2] = 1.0; +}; + +datablock ParticleEmitterData( NukeDebrisSmokeEmitter ) +{ + ejectionPeriodMS = 25; + periodVarianceMS = 5; + + ejectionVelocity = 1.0; // A little oomph at the back end + velocityVariance = 0.5; + + thetaMin = 10.0; + thetaMax = 30.0; + + useEmitterSizes = true; + + particles = "NukeDebrisSmokeParticle"; +}; + +datablock DebrisData( NukeDebris ) +{ + emitters[0] = BurningAshEmitter;//was NukeDebrisSmokeEmitter + emitters[1] = NukeDebrisFireEmitter; + + explosion = DebrisExplosion; + explodeOnMaxBounce = true; + + elasticity = 0.4; + friction = 0.2; + + lifetime = 100.0; + lifetimeVariance = 30.0; + + numBounces = 0; + bounceVariance = 0; +}; + +//bottom smoke +datablock ParticleData(BottomSmoke1) +{ + dragCoefficient = 1.0; + windCoefficient = 0; + gravityCoefficient = -0.01; + inheritedVelFactor = 0.0; + constantAcceleration = 0.0; + lifetimeMS = 15000; + lifetimeVarianceMS = 100; + useInvAlpha = true; + spinRandomMin = -90.0; + spinRandomMax = 500.0; + textureName = "particleTest"; + colors[0] = "0.5 0.5 0.5 0.41"; + colors[1] = "0.4 0.4 0.4 0.41"; + colors[2] = "0.3 0.3 0.3 0.41"; + sizes[0] = 23.4; + sizes[1] = 30.2; + sizes[2] = 30.0; + times[0] = 0.0; + times[1] = 0.7; + times[2] = 1.0; +}; + +datablock ParticleEmitterData(BottomSmokeEmitter1) +{ + ejectionPeriodMS = 3; + periodVarianceMS = 0; + ejectionVelocity = 310.0; + velocityVariance = 0.0; + ejectionOffset = 0.0; + thetaMin = 87; + thetaMax = 87; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + lifetimeMS = 5000; + particles = "BottomSmoke1"; +}; + +datablock ParticleData(BottomSmoke2) +{ + dragCoefficient = 1.0; + windCoefficient = 0; + gravityCoefficient = -0.01; + inheritedVelFactor = 0.0; + constantAcceleration = 0.0; + lifetimeMS = 15000; + lifetimeVarianceMS = 100; + useInvAlpha = true; + spinRandomMin = -90.0; + spinRandomMax = 500.0; + textureName = "particleTest"; + colors[0] = "0.5 0.5 0.5 0.41"; + colors[1] = "0.4 0.4 0.4 0.41"; + colors[2] = "0.3 0.3 0.3 0.41"; + sizes[0] = 23.4; + sizes[1] = 30.2; + sizes[2] = 30.0; + times[0] = 0.0; + times[1] = 0.7; + times[2] = 1.0; +}; + +datablock ParticleEmitterData(BottomSmokeEmitter2) +{ + ejectionPeriodMS = 3; + periodVarianceMS = 0; + ejectionVelocity = 305.0; + velocityVariance = 0.0; + ejectionOffset = 0.0; + thetaMin = 84; + thetaMax = 84; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + lifetimeMS = 5000; + particles = "BottomSmoke2"; +}; + +datablock ParticleData(BottomSmoke3) +{ + dragCoefficient = 1.0; + windCoefficient = 0; + gravityCoefficient = -0.01; + inheritedVelFactor = 0.0; + constantAcceleration = 0.0; + lifetimeMS = 15000; + lifetimeVarianceMS = 100; + useInvAlpha = true; + spinRandomMin = -90.0; + spinRandomMax = 500.0; + textureName = "particleTest"; + colors[0] = "0.5 0.5 0.5 0.41"; + colors[1] = "0.4 0.4 0.4 0.41"; + colors[2] = "0.3 0.3 0.3 0.41"; + sizes[0] = 23.4; + sizes[1] = 30.2; + sizes[2] = 30.0; + times[0] = 0.0; + times[1] = 0.7; + times[2] = 1.0; +}; + +datablock ParticleEmitterData(BottomSmokeEmitter3) +{ + ejectionPeriodMS = 3; + periodVarianceMS = 0; + ejectionVelocity = 290.0; + velocityVariance = 0.0; + ejectionOffset = 0.0; + thetaMin = 81; + thetaMax = 81; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + lifetimeMS = 5000; + particles = "BottomSmoke3"; +}; + +datablock ParticleData(BottomSmoke4) +{ + dragCoefficient = 1.0; + windCoefficient = 0; + gravityCoefficient = -0.01; + inheritedVelFactor = 0.0; + constantAcceleration = 0.0; + lifetimeMS = 15000; + lifetimeVarianceMS = 100; + useInvAlpha = true; + spinRandomMin = -90.0; + spinRandomMax = 500.0; + textureName = "particleTest"; + colors[0] = "0.5 0.5 0.5 0.41"; + colors[1] = "0.4 0.4 0.4 0.41"; + colors[2] = "0.3 0.3 0.3 0.41"; + sizes[0] = 23.4; + sizes[1] = 30.2; + sizes[2] = 30.0; + times[0] = 0.0; + times[1] = 0.7; + times[2] = 1.0; +}; + +datablock ParticleEmitterData(BottomSmokeEmitter4) +{ + ejectionPeriodMS = 3; + periodVarianceMS = 0; + ejectionVelocity = 275.0; + velocityVariance = 0.0; + ejectionOffset = 0.0; + thetaMin = 78; + thetaMax = 78; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + lifetimeMS = 5000; + particles = "BottomSmoke4"; +}; + +datablock ParticleData(BottomSmoke5) +{ + dragCoefficient = 1.0; + windCoefficient = 0; + gravityCoefficient = -0.01; + inheritedVelFactor = 0.0; + constantAcceleration = 0.0; + lifetimeMS = 10000; + lifetimeVarianceMS = 100; + useInvAlpha = true; + spinRandomMin = -90.0; + spinRandomMax = 500.0; + textureName = "particleTest"; + colors[0] = "0.5 0.5 0.5 0.41"; + colors[1] = "0.4 0.4 0.4 0.41"; + colors[2] = "0.3 0.3 0.3 0.41"; + sizes[0] = 23.4; + sizes[1] = 30.2; + sizes[2] = 30.0; + times[0] = 0.0; + times[1] = 0.7; + times[2] = 1.0; +}; + +datablock ParticleEmitterData(BottomSmokeEmitter5) +{ + ejectionPeriodMS = 3; + periodVarianceMS = 0; + ejectionVelocity = 250.0; + velocityVariance = 0.0; + ejectionOffset = 0.0; + thetaMin = 75; + thetaMax = 75; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + lifetimeMS = 5000; + particles = "BottomSmoke5"; +}; + +datablock ParticleData(BottomSmoke6) +{ + dragCoefficient = 1.0; + windCoefficient = 0; + gravityCoefficient = -0.01; + inheritedVelFactor = 0.0; + constantAcceleration = 0.0; + lifetimeMS = 10000; + lifetimeVarianceMS = 100; + useInvAlpha = true; + spinRandomMin = -90.0; + spinRandomMax = 500.0; + textureName = "particleTest"; + colors[0] = "0.5 0.5 0.5 0.41"; + colors[1] = "0.4 0.4 0.4 0.41"; + colors[2] = "0.3 0.3 0.3 0.41"; + sizes[0] = 23.4; + sizes[1] = 30.2; + sizes[2] = 30.0; + times[0] = 0.0; + times[1] = 0.7; + times[2] = 1.0; +}; + +datablock ParticleEmitterData(BottomSmokeEmitter6) +{ + ejectionPeriodMS = 3; + periodVarianceMS = 0; + ejectionVelocity = 235.0; + velocityVariance = 0.0; + ejectionOffset = 0.0; + thetaMin = 75; + thetaMax = 75; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + lifetimeMS = 5000; + particles = "BottomSmoke6"; +}; + +datablock ParticleData(BottomSmoke7) +{ + dragCoefficient = 1.0; + windCoefficient = 0; + gravityCoefficient = -0.01; + inheritedVelFactor = 0.0; + constantAcceleration = 0.0; + lifetimeMS = 10000; + lifetimeVarianceMS = 100; + useInvAlpha = true; + spinRandomMin = -90.0; + spinRandomMax = 500.0; + textureName = "particleTest"; + colors[0] = "0.5 0.5 0.5 0.41"; + colors[1] = "0.4 0.4 0.4 0.41"; + colors[2] = "0.3 0.3 0.3 0.41"; + sizes[0] = 23.4; + sizes[1] = 30.2; + sizes[2] = 30.0; + times[0] = 0.0; + times[1] = 0.7; + times[2] = 1.0; +}; + +datablock ParticleEmitterData(BottomSmokeEmitter7) +{ + ejectionPeriodMS = 3; + periodVarianceMS = 0; + ejectionVelocity = 180.0; + velocityVariance = 0.0; + ejectionOffset = 0.0; + thetaMin = 75; + thetaMax = 75; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + lifetimeMS = 5000; + particles = "BottomSmoke7"; +}; +//middle dust ring +datablock ParticleData(NukeRing) +{ + dragCoefficient = 1.0; + windCoefficient = 0; + gravityCoefficient = -0.01; + inheritedVelFactor = 0.0; + constantAcceleration = 0.0; + lifetimeMS = 15000; + lifetimeVarianceMS = 100; + useInvAlpha = true; + spinRandomMin = -90.0; + spinRandomMax = 500.0; + textureName = "particleTest"; + colors[0] = "0.6 0.3 0.2 0.41"; + colors[1] = "0.6 0.3 0.2 0.41"; + colors[2] = "0.6 0.3 0.2 0.41"; + sizes[0] = 29.4; + sizes[1] = 32.2; + sizes[2] = 33.0; + times[0] = 0.0; + times[1] = 0.7; + times[2] = 1.0; +}; + +datablock ParticleEmitterData(NukeRingEmitter) +{ + ejectionPeriodMS = 10; + periodVarianceMS = 0; + ejectionVelocity = 200.0; + velocityVariance = 0.0; + ejectionOffset = 0.0; + thetaMin = 85; + thetaMax = 85; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + lifetimeMS = 500; + particles = "NukeRing"; +}; +//condensation rings +datablock ParticleData(NukeDust) +{ + dragCoefficient = 1.0; + gravityCoefficient = -0.03; + windCoefficient = 0; + inheritedVelFactor = 0.0; + constantAcceleration = 0.005; + lifetimeMS = 10000; + lifetimeVarianceMS = 100; + useInvAlpha = false; + spinRandomMin = -90.0; + spinRandomMax = 500.0; + textureName = "particleTest"; + colors[0] = "1.0 1.0 1.0 0.2"; + colors[1] = "1.0 1.0 1.0 0.2"; + colors[2] = "1.0 1.0 1.0 0.2"; + sizes[0] = 39.2; + sizes[1] = 42.6; + sizes[2] = 43.0; + times[0] = 0.0; + times[1] = 2.0; + times[2] = 4.0; +}; + +datablock ParticleData(NukeDust2) +{ + dragCoefficient = 1.0; + gravityCoefficient = -0.03; + windCoefficient = 0; + inheritedVelFactor = 0.0; + constantAcceleration = 0.005; + lifetimeMS = 10000; + lifetimeVarianceMS = 100; + useInvAlpha = false; + spinRandomMin = -90.0; + spinRandomMax = 500.0; + textureName = "particleTest"; + colors[0] = "1.0 1.0 1.0 0.2"; + colors[1] = "1.0 1.0 1.0 0.2"; + colors[2] = "1.0 1.0 1.0 0.2"; + sizes[0] = 39.2; + sizes[1] = 42.6; + sizes[2] = 43.0; + times[0] = 0.0; + times[1] = 2.0; + times[2] = 4.0; +}; + +datablock ParticleData(NukeDust3) +{ + dragCoefficient = 1.0; + gravityCoefficient = -0.03; + windCoefficient = 0; + inheritedVelFactor = 0.0; + constantAcceleration = 0.005; + lifetimeMS = 10000; + lifetimeVarianceMS = 100; + useInvAlpha = false; + spinRandomMin = -90.0; + spinRandomMax = 500.0; + textureName = "particleTest"; + colors[0] = "1.0 1.0 1.0 0.2"; + colors[1] = "1.0 1.0 1.0 0.2"; + colors[2] = "1.0 1.0 1.0 0.2"; + sizes[0] = 39.2; + sizes[1] = 42.6; + sizes[2] = 43.0; + times[0] = 0.0; + times[1] = 2.0; + times[2] = 4.0; +}; + +datablock ParticleEmitterData(NukeDustEmitter) +{ + ejectionPeriodMS = 0; + delayMS = 30; + periodVarianceMS = 0; + ejectionVelocity = 475.0; + velocityVariance = 0.0; + ejectionOffset = 0.0; + thetaMin = 110; + thetaMax = 110; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + lifetimeMS = 500; + particles = "NukeDust"; +}; + +datablock ParticleEmitterData(UpAngleNukeDustEmitter) +{ + ejectionPeriodMS = 0; + delayMS = 30; + periodVarianceMS = 0; + ejectionVelocity = 475.0; + velocityVariance = 0.0; + ejectionOffset = 0.0; + thetaMin = 135; + thetaMax = 135; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + lifetimeMS = 500; + particles = "NukeDust3"; +}; + +datablock ParticleEmitterData(DownAngleNukeDustEmitter) +{ + ejectionPeriodMS = 0; + delayMS = 30; + periodVarianceMS = 0; + ejectionVelocity = 475.0; + velocityVariance = 0.0; + ejectionOffset = 0.0; + thetaMin = 135; + thetaMax = 135; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + lifetimeMS = 500; + particles = "NukeDust3"; +}; +//added these ones some 15 hours after the ones up above, thats y there not in order.... +datablock ParticleData(NukeCond1) +{ + dragCoefficient = 1.0; + gravityCoefficient = -0.03; + windCoefficient = 0; + inheritedVelFactor = 0.0; + constantAcceleration = 0.025; + lifetimeMS = 12000; + lifetimeVarianceMS = 100; + useInvAlpha = false; + spinRandomMin = -90.0; + spinRandomMax = 500.0; + textureName = "particleTest"; + colors[0] = "1.0 1.0 1.0 0.2"; + colors[1] = "1.0 1.0 1.0 0.2"; + colors[2] = "1.0 1.0 1.0 0.2"; + sizes[0] = 39.2; + sizes[1] = 42.6; + sizes[2] = 43.0; + times[0] = 0.0; + times[1] = 2.0; + times[2] = 4.0; +}; + +datablock ParticleEmitterData(NukeCondEmitter1) +{ + ejectionPeriodMS = 0; + delayMS = 0; + periodVarianceMS = 0; + ejectionVelocity = 425.0; + velocityVariance = 0.0; + ejectionOffset = 0.0; + thetaMin = 135; + thetaMax = 135; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + lifetimeMS = 5000; + particles = "NukeCond1"; +}; + +datablock ParticleData(NukeCond2) +{ + dragCoefficient = 1.0; + gravityCoefficient = -0.03; + windCoefficient = 0; + inheritedVelFactor = 0.0; + constantAcceleration = 0.025; + lifetimeMS = 12000; + lifetimeVarianceMS = 100; + useInvAlpha = false; + spinRandomMin = -90.0; + spinRandomMax = 500.0; + textureName = "particleTest"; + colors[0] = "1.0 1.0 1.0 0.2"; + colors[1] = "1.0 1.0 1.0 0.2"; + colors[2] = "1.0 1.0 1.0 0.2"; + sizes[0] = 39.2; + sizes[1] = 42.6; + sizes[2] = 43.0; + times[0] = 0.0; + times[1] = 2.0; + times[2] = 4.0; +}; + +datablock ParticleEmitterData(NukeCondEmitter2) +{ + ejectionPeriodMS = 0; + delayMS = 0; + periodVarianceMS = 0; + ejectionVelocity = 475.0; + velocityVariance = 0.0; + ejectionOffset = 0.0; + thetaMin = 120; + thetaMax = 120; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + lifetimeMS = 5000; + particles = "NukeCond2"; +}; + +datablock ParticleData(NukeCond3) +{ + dragCoefficient = 1.0; + gravityCoefficient = -0.03; + windCoefficient = 0; + inheritedVelFactor = 0.0; + constantAcceleration = 0.025; + lifetimeMS = 12000; + lifetimeVarianceMS = 100; + useInvAlpha = false; + spinRandomMin = -90.0; + spinRandomMax = 500.0; + textureName = "particleTest"; + colors[0] = "1.0 1.0 1.0 0.2"; + colors[1] = "1.0 1.0 1.0 0.2"; + colors[2] = "1.0 1.0 1.0 0.2"; + sizes[0] = 39.2; + sizes[1] = 42.6; + sizes[2] = 43.0; + times[0] = 0.0; + times[1] = 2.0; + times[2] = 4.0; +}; + +datablock ParticleEmitterData(NukeCondEmitter3) +{ + ejectionPeriodMS = 0; + delayMS = 0; + periodVarianceMS = 0; + ejectionVelocity = 475.0; + velocityVariance = 0.0; + ejectionOffset = 0.0; + thetaMin = 105; + thetaMax = 105; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + lifetimeMS = 5000; + particles = "NukeCond3"; +}; + +//shockwaves +datablock ShockwaveData(middleShockwave) +{ + width = 500.0; + numSegments = 190; + numVertSegments = 150; + velocity = 5; + acceleration = 1.0; + lifetimeMS = 10500; + height = 50.0; + verticalCurve = 0.25; + 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] = "1.0 0.0 0.0 0.50"; + colors[1] = "1.0 0.0 0.0 0.25"; + colors[2] = "1.0 0.0 0.0 0.0"; + + mapToTerrain = false; + orientToNormal = false; + renderBottom = false; +}; + +datablock ShockwaveData(TopShockwave) +{ + width = 400.0; + numSegments = 190; + numVertSegments = 150; + velocity = 50; + acceleration = 10.0; + lifetimeMS = 10000; + height = 75.0; + verticalCurve = 0.25; + 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] = "1.0 0.5 0.0 0.5"; + colors[1] = "1.0 0.5 0.0 0.5"; + colors[2] = "1.0 0.5 0.0 0.0"; + + mapToTerrain = false; + orientToNormal = false; + renderBottom = true; +}; + +datablock ShockwaveData(bottomShockwave) +{ + width = 200.0; + numSegments = 50; + numVertSegments = 56; + velocity = 200; + acceleration = 1.0; + lifetimeMS = 17000; + height = 10.0; + verticalCurve = 0.25; + is2D = false; + + texture[0] = "special/shockwave4"; + texture[1] = "special/gradient"; + texWrap = 100.0; + + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; + + colors[0] = "1.0 1.0 1.0 0.50"; + colors[1] = "1.0 1.0 1.0 0.25"; + colors[2] = "1.0 1.0 1.0 0.0"; + + mapToTerrain = false; + orientToNormal = false; + renderBottom = true; +}; + + +//-------------------------------------------------------------------------- +// Explosion Particle effects +//-------------------------------------- +datablock ParticleData( NukeCrescentParticle ) +{ + dragCoefficient = 2; + gravityCoefficient = 0.0; + inheritedVelFactor = 0.2; + constantAcceleration = -0.0; + lifetimeMS = 3600; + lifetimeVarianceMS = 000; + textureName = "special/crescent3"; + colors[0] = "0.5 0.0 0.0 1.0"; + colors[1] = "0.5 0.0 0.0 0.5"; + colors[2] = "0.5 0.0 0.0 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( NukeCrescentEmitter ) +{ + 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 = 2000; + particles = "NukeCrescentParticle"; +}; + +//--------------------------------------------------------------------------- +// Explosion/s +//--------------------------------------------------------------------------- + +datablock ExplosionData(BottomSubExplosion1) +{ + explosionShape = "effect_plasma_explosion.dts"; + faceViewer = true; + emitter[0] = BottomSmokeEmitter5; + //emitter[1] = NukeCondEmitter1; + + delayMS = 100; + + + + playSpeed = 0.025; + + sizes[0] = "58.05 58.05 58.05"; + sizes[1] = "58.05 58.05 58.05"; + times[0] = 0.0; + times[1] = 1.0; + +}; + +datablock ExplosionData(BottomSubExplosion2) +{ + explosionShape = "effect_plasma_explosion.dts"; + faceViewer = true; + //emitter[0] = NukeCondEmitter3; + //emitter[1] = NukeCondEmitter2; + + delayMS = 500; + + + + playSpeed = 0.025; + + sizes[0] = "58.05 58.05 58.05"; + sizes[1] = "58.05 58.05 58.05"; + times[0] = 0.0; + times[1] = 1.0; + +}; + +datablock ExplosionData(BottomSubExplosion3) +{ + explosionShape = "effect_plasma_explosion.dts"; + faceViewer = true; + emitter[0] = BottomSmokeEmitter6; + //emitter[1] = NukeCondEmitter3; + + delayMS = 1000; + + + + playSpeed = 0.025; + + sizes[0] = "58.05 58.05 58.05"; + sizes[1] = "58.05 58.05 58.05"; + times[0] = 0.0; + times[1] = 1.0; + +}; + +datablock ExplosionData(BottomExplosion) +{ + soundProfile = NukeBottomExplosionSound; + + subExplosion[0] = BottomSubExplosion1; + subExplosion[1] = BottomSubExplosion2; + subExplosion[2] = BottomSubExplosion3; + + shockwave = bottomShockwave; + shockwaveOnTerrain = true; + + debris = NukeDebris; + debrisThetaMin = 10; + debrisThetaMax = 60; + debrisNum = 15; + debrisNumVariance = 5; + debrisVelocity = 75.0; + debrisVelocityVariance = 5.0; + + particleEmitter = PlasmaExplosionEmitter; + particleDensity = 10000; + particleRadius = 50.25; + faceViewer = true; + + emitter[0] = BottomSmokeEmitter1; + emitter[1] = BottomSmokeEmitter2; + emitter[2] = BottomSmokeEmitter3; + emitter[3] = BottomSmokeEmitter4; + + shakeCamera = true; + camShakeFreq = "9900.0 8900.0 7800.0"; + camShakeAmp = "1000.0 1000.0 1000.0"; + camShakeDuration = 5.0; + camShakeRadius = 125.0; +}; + +datablock ExplosionData(MidSubExplosion1) +{ + explosionShape = "effect_plasma_explosion.dts"; + faceViewer = true; + + delayMS = 100; + + + + playSpeed = 0.025; + + sizes[0] = "44.05 44.05 44.05"; + sizes[1] = "44.05 44.05 44.05"; + times[0] = 0.0; + times[1] = 1.0; + +}; + +datablock ExplosionData(MidSubExplosion2) +{ + explosionShape = "effect_plasma_explosion.dts"; + faceViewer = true; + + delayMS = 500; + + + + playSpeed = 0.025; + + sizes[0] = "44.05 44.05 44.05"; + sizes[1] = "44.05 44.05 44.05"; + times[0] = 0.0; + times[1] = 1.0; + +}; + +datablock ExplosionData(MidSubExplosion3) +{ + explosionShape = "effect_plasma_explosion.dts"; + faceViewer = true; + + delayMS = 1000; + + + + playSpeed = 0.025; + + sizes[0] = "44.05 44.05 44.05"; + sizes[1] = "44.05 44.05 44.05"; + times[0] = 0.0; + times[1] = 1.0; + +}; + +datablock ExplosionData(MidExplosion) +{ + soundProfile = NukeExplosionSound; + + subExplosion[0] = MidSubExplosion1; + subExplosion[1] = MidSubExplosion2; + subExplosion[2] = MidSubExplosion3; + + //shockwave = AirBlastShockwave; + //shockwaveOnTerrain = false; + + debris = NukeDebris; + debrisThetaMin = 10; + debrisThetaMax = 60; + debrisNum = 15; + debrisNumVariance = 5; + debrisVelocity = 75.0; + debrisVelocityVariance = 5.0; + + particleEmitter = PlasmaExplosionEmitter; + particleDensity = 10000; + particleRadius = 40.25; + faceViewer = true; + + emitter[0] = NukeExplosionSmokeEmitter; + emitter[1] = NukeCrescentEmitter; + //emitter[2] = NukeDustEmitter; + + shakeCamera = true; + camShakeFreq = "9900.0 8900.0 7800.0"; + camShakeAmp = "1000.0 1000.0 1000.0"; + camShakeDuration = 5.0; + camShakeRadius = 50.0; +}; + +datablock ExplosionData(RingExplosion) +{ + soundProfile = NukeExplosionSound; + + subExplosion[0] = MidSubExplosion1; + subExplosion[1] = MidSubExplosion2; + subExplosion[2] = MidSubExplosion3; + + //shockwave = AirBlastShockwave; + //shockwaveOnTerrain = false; + + debris = NukeDebris; + debrisThetaMin = 10; + debrisThetaMax = 60; + debrisNum = 15; + debrisNumVariance = 5; + debrisVelocity = 75.0; + debrisVelocityVariance = 5.0; + + + particleEmitter = PlasmaExplosionEmitter; + particleDensity = 10000; + particleRadius = 40.25; + faceViewer = true; + + emitter[0] = NukeCondEmitter1; + emitter[1] = NukeCondEmitter2; + emitter[2] = NukeCondEmitter3; + emitter[3] = NukeRingEmitter; + + shakeCamera = true; + camShakeFreq = "9900.0 8900.0 7800.0"; + camShakeAmp = "1000.0 1000.0 1000.0"; + camShakeDuration = 5.0; + camShakeRadius = 150.0; +}; + +datablock ExplosionData(TopSubExplosion1) +{ + explosionShape = "effect_plasma_explosion.dts"; + faceViewer = true; + soundProfile = NukeTopExplosionSound; + + delayMS = 100; + + + + playSpeed = 0.025; + + sizes[0] = "155.05 130.05 130.05"; + sizes[1] = "305.05 280.05 280.05"; + times[0] = 0.0; + times[1] = 1.0; + +}; + +datablock ExplosionData(TopSubExplosion2) +{ + explosionShape = "effect_plasma_explosion.dts"; + faceViewer = true; + soundProfile = NukeTopExplosionSound; + + delayMS = 500; + + + playSpeed = 0.025; + + sizes[0] = "155.05 130.05 130.05"; + sizes[1] = "305.05 280.05 280.05"; + times[0] = 0.0; + times[1] = 1.0; + +}; + +datablock ExplosionData(TopSubExplosion3) +{ + explosionShape = "effect_plasma_explosion.dts"; + faceViewer = true; + soundProfile = NukeTopExplosionSound; + + delayMS = 1000; + + + + playSpeed = 0.025; + + sizes[0] = "155.05 130.05 130.05"; + sizes[1] = "305.05 280.05 280.05"; + times[0] = 0.0; + times[1] = 1.0; + +}; + +datablock ExplosionData(TopSubExplosion4) +{ + explosionShape = "effect_plasma_explosion.dts"; + faceViewer = true; + soundProfile = NukeTopExplosionSound; + + delayMS = 100; + + + + playSpeed = 0.025; + + sizes[0] = "155.05 130.05 130.05"; + sizes[1] = "305.05 280.05 280.05"; + times[0] = 0.0; + times[1] = 1.0; + +}; + +datablock ExplosionData(TopSubExplosion5) +{ + explosionShape = "effect_plasma_explosion.dts"; + faceViewer = true; + soundProfile = NukeTopExplosionSound; + + delayMS = 500; + + + playSpeed = 0.025; + + sizes[0] = "155.05 130.05 130.05"; + sizes[1] = "305.05 280.05 280.05"; + times[0] = 0.0; + times[1] = 1.0; + +}; + +datablock ExplosionData(TopSubExplosion6) +{ + explosionShape = "effect_plasma_explosion.dts"; + faceViewer = true; + soundProfile = NukeTopExplosionSound; + + + delayMS = 1000; + + playSpeed = 0.025; + + sizes[0] = "155.05 130.05 130.05"; + sizes[1] = "305.05 280.05 280.05"; + times[0] = 0.0; + times[1] = 1.0; + +}; + +datablock ExplosionData(TopExplosion) +{ + soundProfile = NukeTopExplosionSound; + + subExplosion[0] = TopSubExplosion1; + subExplosion[1] = TopSubExplosion2; + subExplosion[2] = TopSubExplosion3; + subExplosion[3] = TopSubExplosion4; + subExplosion[4] = TopSubExplosion5; + subExplosion[5] = TopSubExplosion6; + + shockwave = TopShockwave; + shockwaveOnTerrain = false; + + debris = NukeDebris; + debrisThetaMin = 10; + debrisThetaMax = 60; + debrisNum = 250; + debrisNumVariance = 5; + debrisVelocity = 125.0; + debrisVelocityVariance = 5.0; + + particleEmitter = PlasmaExplosionEmitter; + particleDensity = 15000; + particleRadius = 275.25; + faceViewer = true; + + emitter[0] = NukeCrescentEmitter; + emitter[1] = NukeDustEmitter; + emitter[2] = UpAngleNukeDustEmitter; + //emitter[2] = DownAngleNukeDustEmitter; + + shakeCamera = true; + camShakeFreq = "1000.0 1000.0 1000.0"; + camShakeAmp = "1000.0 900.0 1500.0"; + camShakeDuration = 8.0; + camShakeRadius = 1500.0; +}; + +//--------------------------------------------------------------------------- +// Smoke particles +//--------------------------------------------------------------------------- +datablock ParticleData(CoolSmokeParticle) +{ + dragCoeffiecient = 0.0; + gravityCoefficient = -0.0; // rises slowly + inheritedVelFactor = 0.00; + + lifetimeMS = 1700; // lasts 2 second + lifetimeVarianceMS = 150; // ...more or less + + textureName = "particleTest"; + + useInvAlpha = true; + spinRandomMin = -30.0; + spinRandomMax = 30.0; + + colors[0] = "0.5 0.3 0.1 1.0"; + colors[1] = "0.5 0.3 0.1 0.5"; + colors[2] = "0.5 0.3 0.1 0.1"; + + sizes[0] = 5.25; + sizes[1] = 6.0; + sizes[2] = 8.0; + + times[0] = 0.0; + times[1] = 0.2; + times[2] = 1.0; +}; + +datablock ParticleEmitterData(CoolSmokeEmitter) +{ + ejectionPeriodMS = 10; + periodVarianceMS = 0; + + ejectionVelocity = 0.25; + velocityVariance = 0.50; + + thetaMin = -10.0; + thetaMax = 10.0; + + particles = "CoolSmokeParticle"; +}; + +datablock ParticleData(CannonSmokeParticle) +{ + dragCoeffiecient = 0.0; + gravityCoefficient = -0.0; // rises slowly + inheritedVelFactor = 0.00; + + lifetimeMS = 10700; // lasts 2 second + lifetimeVarianceMS = 150; // ...more or less + + textureName = "special/flareSpark"; + + useInvAlpha = false; + spinRandomMin = -30.0; + spinRandomMax = 30.0; + + colors[0] = "0.0 1.0 0.4 0.3"; + colors[1] = "0.0 1.0 0.4 0.3"; + colors[2] = "0.0 1.0 0.4 0.1"; + + sizes[0] = 45.25; + sizes[1] = 46.0; + sizes[2] = 38.0; + + times[0] = 0.0; + times[1] = 0.2; + times[2] = 1.0; +}; + +datablock ParticleEmitterData(CannonSmokeEmitter) +{ + ejectionPeriodMS = 10; + periodVarianceMS = 0; + + ejectionVelocity = 0.25; + velocityVariance = 0.50; + + thetaMin = -10.0; + thetaMax = 10.0; + + particles = "CannonSmokeParticle"; +}; + +datablock ParticleData(BurningAshParticle) +{ + dragCoeffiecient = 0.0; + gravityCoefficient = -0.0; // rises slowly + inheritedVelFactor = 0.00; + + lifetimeMS = 700; // lasts 2 second + lifetimeVarianceMS = 150; // ...more or less + + textureName = "particleTest"; + + useInvAlpha = true; + spinRandomMin = -30.0; + spinRandomMax = 30.0; + + colors[0] = "1.0 1.0 0.0 1.0"; + colors[1] = "0.8 0.5 0.0 1.0"; + colors[2] = "0.5 0.2 0.0 0.0"; + + sizes[0] = 0.25; + sizes[1] = 0.15; + sizes[2] = 0.05; + + times[0] = 0.0; + times[1] = 0.2; + times[2] = 1.0; +}; + +datablock ParticleEmitterData(BurningAshEmitter) +{ + ejectionPeriodMS = 5; + periodVarianceMS = 0; + + ejectionVelocity = 1.25; + velocityVariance = 0.50; + + thetaMin = 0.0; + thetaMax = 0.0; + + particles = "BurningAshParticle"; +}; + + +//-------------------------------------------------------------------------- +// Projectile +//-------------------------------------- +datablock TargetProjectileData(RedTargeterBeam) +{ + directDamage = 0.0; + hasDamageRadius = false; + indirectDamage = 0.0; + damageRadius = 0.0; + velInheritFactor = 1.0; + + maxRifleRange = 1000; + beamColor = "1.0 0.1 0.1"; + + startBeamWidth = 0.50; + pulseBeamWidth = 1.15; + beamFlareAngle = 3.0; + minFlareSize = 0.0; + maxFlareSize = 400.0; + pulseSpeed = 6.0; + pulseLength = 0.150; + + textureName[0] = "special/nonlingradient"; + textureName[1] = "special/flare"; + textureName[2] = "special/pulse"; + textureName[3] = "special/expFlare"; + beacon = true; +}; + +datablock TargetProjectileData(NukeTargeterBeam) +{ + directDamage = 0.0; + hasDamageRadius = false; + indirectDamage = 0.0; + damageRadius = 0.0; + velInheritFactor = 1.0; + + maxRifleRange = 1000; + beamColor = "0.1 1.0 1.0"; + + startBeamWidth = 0.20; + pulseBeamWidth = 0.15; + beamFlareAngle = 3.0; + minFlareSize = 0.0; + maxFlareSize = 400.0; + pulseSpeed = 6.0; + pulseLength = 0.150; + + textureName[0] = "special/nonlingradient"; + textureName[1] = "special/flare"; + textureName[2] = "special/pulse"; + textureName[3] = "special/expFlare"; + beacon = true; +}; + +datablock LinearFlareProjectileData(TargeterShot) +{ + scale = "0.1 0.1 0.1"; + faceViewer = true; + directDamage = 0.0; + hasDamageRadius = true; + indirectDamage = 0.01; + damageRadius = 0.01; + radiusDamageType = $DamageType::Plasma; + kickBackStrength = 0; + + explosion = "SniperExplosion"; + splash = PlasmaSplash; + + + dryVelocity = 5095.0; + wetVelocity = -1; + velInheritFactor = 0.3; + fizzleTimeMS = 29000; + lifetimeMS = 30000; + explodeOnDeath = false; + reflectOnWaterImpactAngle = 0.0; + explodeOnWaterImpact = true; + deflectionOnWaterImpact = 0.0; + fizzleUnderwaterMS = -1; + + //activateDelayMS = 100; + activateDelayMS = -1; + + size[0] = 0.2; + size[1] = 0.5; + size[2] = 0.1; + + + numFlares = 35; + flareColor = "0 0 0"; + flareModTexture = "flaremod"; + flareBaseTexture = "flarebase"; + + sound = PlasmaProjectileSound; + fireSound = PlasmaFireSound; + wetFireSound = PlasmaFireWetSound; + + hasLight = false; +}; + +datablock LinearFlareProjectileData(NukeBolt) +{ + scale = "70.0 70.0 70.0"; + faceViewer = true; + directDamage = 0.0; + hasDamageRadius = true; + indirectDamage = 0.02; + damageRadius = 1000.0; + radiusDamageType = $DamageType::Plasma; //CHANGE BACK TO FIRE!!! + kickBackStrength = 55000; + + explosion = "BottomExplosion"; + splash = PlasmaSplash; + + baseEmitter = CannonSmokeEmitter; + + dryVelocity = 295.0; + wetVelocity = -1; + velInheritFactor = 0.3; + fizzleTimeMS = 29000; + lifetimeMS = 30000; + explodeOnDeath = false; + reflectOnWaterImpactAngle = 0.0; + explodeOnWaterImpact = true; + deflectionOnWaterImpact = 0.0; + fizzleUnderwaterMS = -1; + + //activateDelayMS = 100; + activateDelayMS = -1; + + size[0] = 0.2; + size[1] = 0.5; + size[2] = 0.1; + + + numFlares = 350; + flareColor = "1 0.45 0.25"; + flareModTexture = "flaremod"; + flareBaseTexture = "flarebase"; + + sound = PlasmaProjectileSound; + fireSound = PlasmaFireSound; + wetFireSound = PlasmaFireWetSound; + + hasLight = true; + lightRadius = 3.0; + lightColor = "1 0.75 0.25"; +}; + +datablock LinearProjectileData(UpPart1) +{ + projectileShapeName = "weapon_missile_projectile.dts"; + directDamage = 0.2; + hasDamageRadius = true; + damageRadius = 350.0; + indirectDamage = 1.01; + kickBackStrength = 3000.0; + radiusDamageType = $DamageType::Fire; + + explosion = "MidExplosion"; + splash = PlasmaSplash; + + dryVelocity = 300; + wetVelocity = 300; + velInheritFactor = 0; + fizzleTimeMS = 0; + lifetimeMS = 237; + explodeOnDeath = true; + reflectOnWaterImpactAngle = 0; + explodeOnWaterImpact = true; + deflectionOnWaterImpact = 0.0; + fizzleUnderwaterMS = -1; + + activateDelayMS = 200; + + + sound = NukeUpProjectileSound; + fireSound = PlasmaFireSound; + wetFireSound = PlasmaFireWetSound; + + hasLight = true; + lightRadius = 3.0; + lightColor = "1 0.75 0.25"; +}; + +datablock LinearProjectileData(UpPart2) +{ + projectileShapeName = "weapon_missile_projectile.dts"; + directDamage = 0.2; + hasDamageRadius = true; + damageRadius = 350.0; + indirectDamage = 1.1; + kickBackStrength = 3000.0; + radiusDamageType = $DamageType::Fire; + + explosion = "MidExplosion"; + splash = PlasmaSplash; + + dryVelocity = 300; + wetVelocity = 300; + velInheritFactor = 0; + fizzleTimeMS = 0; + lifetimeMS = 237; + explodeOnDeath = true; + reflectOnWaterImpactAngle = 0; + explodeOnWaterImpact = true; + deflectionOnWaterImpact = 0.0; + fizzleUnderwaterMS = -1; + + activateDelayMS = 200; + + sound = NukeUpProjectileSound; + + hasLight = true; + lightRadius = 3.0; + lightColor = "1 0.75 0.25"; +}; + +datablock LinearProjectileData(UpPart3) +{ + projectileShapeName = "weapon_missile_projectile.dts"; + directDamage = 0.2; + hasDamageRadius = true; + damageRadius = 350.0; + indirectDamage = 1.1; + kickBackStrength = 3000.0; + radiusDamageType = $DamageType::Fire; + + explosion = "MidExplosion"; + splash = PlasmaSplash; + + dryVelocity = 300; + wetVelocity = 300; + velInheritFactor = 0; + fizzleTimeMS = 0; + lifetimeMS = 237; + explodeOnDeath = true; + reflectOnWaterImpactAngle = 0; + explodeOnWaterImpact = true; + deflectionOnWaterImpact = 0.0; + fizzleUnderwaterMS = -1; + + activateDelayMS = 200; + + sound = NukeUpProjectileSound; + fireSound = PlasmaFireSound; + wetFireSound = PlasmaFireWetSound; + + hasLight = true; + lightRadius = 3.0; + lightColor = "1 0.75 0.25"; +}; + +datablock LinearProjectileData(UpPartRing) +{ + projectileShapeName = "weapon_missile_projectile.dts"; + directDamage = 0.2; + hasDamageRadius = true; + damageRadius = 450.0; + indirectDamage = 1.5; + kickBackStrength = 5000.0; + radiusDamageType = $DamageType::Fire; + + explosion = "RingExplosion"; + splash = PlasmaSplash; + + dryVelocity = 300; + wetVelocity = 300; + velInheritFactor = 0; + fizzleTimeMS = 0; + lifetimeMS = 237; + explodeOnDeath = true; + reflectOnWaterImpactAngle = 0; + explodeOnWaterImpact = true; + deflectionOnWaterImpact = 0.0; + fizzleUnderwaterMS = -1; + + activateDelayMS = 200; + + sound = PlasmaProjectileSound; + fireSound = PlasmaFireSound; + wetFireSound = PlasmaFireWetSound; + + hasLight = true; + lightRadius = 3.0; + lightColor = "1 0.75 0.25"; +}; +datablock LinearProjectileData(UpPart4) +{ + projectileShapeName = "weapon_missile_projectile.dts"; + directDamage = 0.2; + hasDamageRadius = true; + damageRadius = 350.0; + indirectDamage = 1.1; + kickBackStrength = 3000.0; + radiusDamageType = $DamageType::Fire; + + explosion = "MidExplosion"; + splash = PlasmaSplash; + + dryVelocity = 300; + wetVelocity = 300; + velInheritFactor = 0; + fizzleTimeMS = 0; + lifetimeMS = 237; + explodeOnDeath = true; + reflectOnWaterImpactAngle = 0; + explodeOnWaterImpact = true; + deflectionOnWaterImpact = 0.0; + fizzleUnderwaterMS = -1; + + activateDelayMS = 200; + + sound = NukeUpProjectileSound; + fireSound = PlasmaFireSound; + wetFireSound = PlasmaFireWetSound; + + hasLight = true; + lightRadius = 3.0; + lightColor = "1 0.75 0.25"; +}; + +datablock LinearProjectileData(UpPart5) +{ + projectileShapeName = "weapon_missile_projectile.dts"; + directDamage = 0.2; + hasDamageRadius = true; + damageRadius = 350.0; + indirectDamage = 1.1; + kickBackStrength = 3000.0; + radiusDamageType = $DamageType::Fire; + + explosion = "MidExplosion"; + splash = PlasmaSplash; + + dryVelocity = 300; + wetVelocity = 300; + velInheritFactor = 0; + fizzleTimeMS = 0; + lifetimeMS = 237; + explodeOnDeath = true; + reflectOnWaterImpactAngle = 0; + explodeOnWaterImpact = true; + deflectionOnWaterImpact = 0.0; + fizzleUnderwaterMS = -1; + + activateDelayMS = 200; + + sound = NukeUpProjectileSound; + fireSound = PlasmaFireSound; + wetFireSound = PlasmaFireWetSound; + + hasLight = true; + lightRadius = 3.0; + lightColor = "1 0.75 0.25"; +}; + +datablock LinearProjectileData(UpPart6) +{ + projectileShapeName = "weapon_missile_projectile.dts"; + directDamage = 0.2; + hasDamageRadius = true; + damageRadius = 350.0; + indirectDamage = 1.1; + kickBackStrength = 3000.0; + radiusDamageType = $DamageType::Fire; + + explosion = "MidExplosion"; + splash = PlasmaSplash; + + dryVelocity = 300; + wetVelocity = 300; + velInheritFactor = 0; + fizzleTimeMS = 0; + lifetimeMS = 237; + explodeOnDeath = true; + reflectOnWaterImpactAngle = 0; + explodeOnWaterImpact = true; + deflectionOnWaterImpact = 0.0; + fizzleUnderwaterMS = -1; + + activateDelayMS = 200; + + sound = NukeUpProjectileSound; + fireSound = PlasmaFireSound; + wetFireSound = PlasmaFireWetSound; + + hasLight = true; + lightRadius = 3.0; + lightColor = "1 0.75 0.25"; +}; + +datablock LinearProjectileData(UpPart7) +{ + projectileShapeName = "weapon_missile_projectile.dts"; + directDamage = 0.2; + hasDamageRadius = true; + damageRadius = 350.0; + indirectDamage = 1.1; + kickBackStrength = 3000.0; + radiusDamageType = $DamageType::Fire; + + explosion = "MidExplosion"; + splash = PlasmaSplash; + + dryVelocity = 300; + wetVelocity = 300; + velInheritFactor = 0; + fizzleTimeMS = 0; + lifetimeMS = 237; + explodeOnDeath = true; + reflectOnWaterImpactAngle = 0; + explodeOnWaterImpact = true; + deflectionOnWaterImpact = 0.0; + fizzleUnderwaterMS = -1; + + activateDelayMS = 200; + + sound = NukeUpProjectileSound; + fireSound = PlasmaFireSound; + wetFireSound = PlasmaFireWetSound; + + hasLight = true; + lightRadius = 3.0; + lightColor = "1 0.75 0.25"; +}; + +datablock LinearProjectileData(UpPart8) +{ + projectileShapeName = "weapon_missile_projectile.dts"; + directDamage = 0.2; + hasDamageRadius = true; + damageRadius = 350.0; + indirectDamage = 1.1; + kickBackStrength = 3000.0; + radiusDamageType = $DamageType::Fire; + + explosion = "MidExplosion"; + splash = PlasmaSplash; + + dryVelocity = 300; + wetVelocity = 300; + velInheritFactor = 0; + fizzleTimeMS = 0; + lifetimeMS = 237; + explodeOnDeath = true; + reflectOnWaterImpactAngle = 0; + explodeOnWaterImpact = true; + deflectionOnWaterImpact = 0.0; + fizzleUnderwaterMS = -1; + + activateDelayMS = 200; + + sound = NukeUpProjectileSound; + fireSound = PlasmaFireSound; + wetFireSound = PlasmaFireWetSound; + + hasLight = true; + lightRadius = 3.0; + lightColor = "1 0.75 0.25"; +}; + +datablock LinearProjectileData(Top) +{ + + projectileShapeName = "weapon_missile_projectile.dts"; + directDamage = 0.2; + hasDamageRadius = true; + damageRadius = 550.0; + indirectDamage = 1.1; + kickBackStrength = 9500.0; + radiusDamageType = $DamageType::Fire; + + explosion = "TopExplosion"; + splash = PlasmaSplash; + + dryVelocity = 300; + wetVelocity = 300; + velInheritFactor = 0; + fizzleTimeMS = 0; + lifetimeMS = 313; + explodeOnDeath = true; + reflectOnWaterImpactAngle = 0; + explodeOnWaterImpact = true; + deflectionOnWaterImpact = 0.0; + fizzleUnderwaterMS = -1; + + activateDelayMS = 200; + + + sound = PlasmaProjectileSound; + fireSound = PlasmaFireSound; + wetFireSound = PlasmaFireWetSound; + + hasLight = true; + lightRadius = 3.0; + lightColor = "1 0.75 0.25"; +}; + +datablock GrenadeProjectileData(DebrisGrenade) +{ + projectileShapeName = "grenade_projectile.dts"; + scale = "0.1 0.1 0.1"; + emitterDelay = -1; + directDamage = 0.0; + hasDamageRadius = true; + indirectDamage = 0.40; + damageRadius = 5.0; + radiusDamageType = $DamageType::Fire; + kickBackStrength = 1500; + bubbleEmitTime = 1.0; + + sound = GrenadeProjectileSound; + explosion = "PlasmaBoltExplosion"; + underwaterExplosion = "UnderwaterGrenadeExplosion"; + velInheritFactor = 0.5; + splash = GrenadeSplash; + + + baseEmitter = MissileSmokeEmitter; + delayEmitter = MissileFireEmitter; + puffEmitter = MissilePuffEmitter; + bubbleEmitter = GrenadeBubbleEmitter; + bubbleEmitTime = 1.0; + + exhaustEmitter = MissileLauncherExhaustEmitter; + exhaustTimeMs = 300; + exhaustNodeName = "muzzlePoint1"; + + grenadeElasticity = 0.35; + grenadeFriction = 0.2; + armingDelayMS = 1000; + muzzleVelocity = 47.00; + drag = 0.1; +}; + +datablock GrenadeProjectileData(FireDebrisGrenade) +{ + projectileShapeName = "grenade_projectile.dts"; + scale = "0.1 0.1 0.1"; + emitterDelay = -1; + directDamage = 0.0; + hasDamageRadius = true; + indirectDamage = 0.20; + damageRadius = 2.0; + radiusDamageType = $DamageType::Fire; + kickBackStrength = 1500; + bubbleEmitTime = 1.0; + + sound = GrenadeProjectileSound; + explosion = "PlasmaBoltExplosion"; + underwaterExplosion = "UnderwaterGrenadeExplosion"; + velInheritFactor = 0.5; + splash = GrenadeSplash; + + + baseEmitter = BurningAshEmitter; + + grenadeElasticity = 0.35; + grenadeFriction = 0.1; + armingDelayMS = 1000; + muzzleVelocity = 107.00; + drag = 0.1; +}; + +//-------------------------------------------------------------------------- +// Ammo +//-------------------------------------- + +datablock ItemData(NukeAmmo) +{ + className = Ammo; + catagory = "Ammo"; + shapeFile = "ammo_mortar.dts"; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 2; + pickUpName = "some Nuke ammo"; + + computeCRC = true; + +}; + +//-------------------------------------------------------------------------- +// Weapon +//-------------------------------------- +datablock ItemData(Nuke) +{ + className = Weapon; + catagory = "Spawn Items"; + shapeFile = "weapon_mortar.dts"; + image = NukeImage; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 2; + pickUpName = "a Nuke"; + + computeCRC = true; + emap = true; +}; + +datablock ShapeBaseImageData(NukeImage) +{ + className = WeaponImage; + shapeFile = "weapon_mortar.dts"; + item = Nuke; + //ammo = NukeAmmo; + offset = "0 0 0"; + emap = true; + UsesEnergy = true; + fireEnergy = 1; + minEnergy = 1; + + projectile = TargeterShot; + projectileType = LinearFlareProjectile; + + stateName[0] = "Activate"; + stateTransitionOnTimeout[0] = "ActivateReady"; + stateTimeoutValue[0] = 0.5; + stateSequence[0] = "Activate"; + stateSound[0] = NukeSwitchSound; + + stateName[1] = "ActivateReady"; + stateTransitionOnLoaded[1] = "Ready"; + stateTransitionOnNoAmmo[1] = "NoAmmo"; + + 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] = NukeFireSound; + + stateName[4] = "Reload"; + stateTransitionOnNoAmmo[4] = "NoAmmo"; + stateTransitionOnTimeout[4] = "Ready"; + stateTimeoutValue[4] = 2.0; + stateAllowImageChange[4] = false; + stateSequence[4] = "Reload"; + stateSound[4] = NukeReloadSound; + + 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"; +}; + +function NukeBolt::onExplode(%data, %proj, %pos, %mod) +{ +%start = getSimTime(); +nukewind(VectorAdd(%pos,"0 0 50"),%start,6000); + +if (%data.hasDamageRadius) +RadiusExplosion(%proj, %pos, %data.damageRadius, %data.indirectDamage, %data.kickBackStrength, %proj.sourceObject, %data.radiusDamageType); +for(%i=0;%i<1;%i++) +{ +%p = new LinearProjectile() +{ +dataBlock = UpPart1; +initialDirection = "0 0 1"; +initialPosition = %pos; + +}; +MissionCleanup.add(%p); +} +//raidusWhiteout(%pos, 2500.0, 0.75); +whiteout(%pos,1000,2500); //used my own. :P + Parent::onExplode(%data, %proj, %pos, %mod); + + +} + +function UpPart1::onExplode(%data, %proj, %pos, %mod) +{ +if (%data.hasDamageRadius) +RadiusExplosion(%proj, %pos, %data.damageRadius, %data.indirectDamage, %data.kickBackStrength, %proj.sourceObject, %data.radiusDamageType); +for(%i=0;%i<1;%i++) +{ +%p = new LinearProjectile() +{ +dataBlock = UpPart2; +initialDirection = "0 0 1"; +initialPosition = %pos; + +}; +MissionCleanup.add(%p); +} +} + +function UpPart2::onExplode(%data, %proj, %pos, %mod) +{ +if (%data.hasDamageRadius) +RadiusExplosion(%proj, %pos, %data.damageRadius, %data.indirectDamage, %data.kickBackStrength, %proj.sourceObject, %data.radiusDamageType); +for(%i=0;%i<1;%i++) +{ +%p = new LinearProjectile() +{ +dataBlock = UpPart3; +initialDirection = "0 0 1"; +initialPosition = %pos; + +}; +MissionCleanup.add(%p); +} +} + +function UpPart3::onExplode(%data, %proj, %pos, %mod) +{ +if (%data.hasDamageRadius) +RadiusExplosion(%proj, %pos, %data.damageRadius, %data.indirectDamage, %data.kickBackStrength, %proj.sourceObject, %data.radiusDamageType); +for(%i=0;%i<1;%i++) +{ +%p = new LinearProjectile() +{ +dataBlock = UpPartRing; +initialDirection = "0 0 1"; +initialPosition = %pos; + +}; +MissionCleanup.add(%p); +} +} + +function UpPartRing::onExplode(%data, %proj, %pos, %mod) +{ +if (%data.hasDamageRadius) +RadiusExplosion(%proj, %pos, %data.damageRadius, %data.indirectDamage, %data.kickBackStrength, %proj.sourceObject, %data.radiusDamageType); +for(%i=0;%i<1;%i++) +{ +%p = new LinearProjectile() +{ +dataBlock = UpPart4; +initialDirection = "0 0 1"; +initialPosition = %pos; + +}; +MissionCleanup.add(%p); +} + +} +function UpPart4::onExplode(%data, %proj, %pos, %mod) +{ +if (%data.hasDamageRadius) +RadiusExplosion(%proj, %pos, %data.damageRadius, %data.indirectDamage, %data.kickBackStrength, %proj.sourceObject, %data.radiusDamageType); +for(%i=0;%i<1;%i++) +{ +%p = new LinearProjectile() +{ +dataBlock = UpPart5; +initialDirection = "0 0 1"; +initialPosition = %pos; + +}; +MissionCleanup.add(%p); +} +} + +function UpPart5::onExplode(%data, %proj, %pos, %mod) +{ +if (%data.hasDamageRadius) +RadiusExplosion(%proj, %pos, %data.damageRadius, %data.indirectDamage, %data.kickBackStrength, %proj.sourceObject, %data.radiusDamageType); +for(%i=0;%i<1;%i++) +{ +%p = new LinearProjectile() +{ +dataBlock = UpPart6; +initialDirection = "0 0 1"; +initialPosition = %pos; + +}; +MissionCleanup.add(%p); +} +} + +function UpPart6::onExplode(%data, %proj, %pos, %mod) +{ +if (%data.hasDamageRadius) +RadiusExplosion(%proj, %pos, %data.damageRadius, %data.indirectDamage, %data.kickBackStrength, %proj.sourceObject, %data.radiusDamageType); +for(%i=0;%i<1;%i++) +{ +%p = new LinearProjectile() +{ +dataBlock = UpPart7; +initialDirection = "0 0 1"; +initialPosition = %pos; + +}; +MissionCleanup.add(%p); +} +} + +function UpPart7::onExplode(%data, %proj, %pos, %mod) +{ +if (%data.hasDamageRadius) +RadiusExplosion(%proj, %pos, %data.damageRadius, %data.indirectDamage, %data.kickBackStrength, %proj.sourceObject, %data.radiusDamageType); +for(%i=0;%i<1;%i++) +{ +%p = new LinearProjectile() +{ +dataBlock = Top; +initialDirection = "0 0 1"; +initialPosition = %pos; + +}; +MissionCleanup.add(%p); +} +} + +function Top::onExplode(%data, %proj, %pos, %mod) +{ + if (%data.hasDamageRadius) + RadiusExplosion(%proj, %pos, %data.damageRadius, %data.indirectDamage, %data.kickBackStrength, %proj.sourceObject, %data.radiusDamageType); + for(%i=0;%i<75;%i++) + { + %x = (getRandom() * 2) - 1; //-1 to 1, ie: full circle + %y = (getRandom() * 2) - 1; + %z = (getRandom() * 2) - 1; + %vec = %x SPC %y SPC %z; //Shoot any direction + %p = new GrenadeProjectile() { + dataBlock = DebrisGrenade; + initialDirection = %vec; + initialPosition = %pos; + + }; + MissionCleanup.add(%p); + } + if (%data.hasDamageRadius) + RadiusExplosion(%proj, %pos, %data.damageRadius, %data.indirectDamage, %data.kickBackStrength, %proj.sourceObject, %data.radiusDamageType); + for(%i=0;%i<0;%i++) + { + %x = (getRandom() * 2) - 1; //-1 to 1, ie: full circle + %y = (getRandom() * 2) - 1; + %z = (getRandom() * 2) - 1; + %vec = %x SPC %y SPC %z; //Shoot any direction + %p = new GrenadeProjectile() { + dataBlock = FireDebrisGrenade; + initialDirection = %vec; + initialPosition = %pos; + + }; + MissionCleanup.add(%p); + } + + %Ash = new Precipitation() { + position = "0 0 0"; + rotation = "1 0 0 0"; + scale = "1 1 1"; + dataBlock = "Snow"; + percentage = "1"; + color1 = "0.3 0.3 0.3 1"; + color2 = "0.3 0.3 0.3 1"; + color3 = "0.3 0.3 0.3 1"; + offsetSpeed = "0.25"; + minVelocity = "0.25"; + maxVelocity = "1.5"; + maxNumDrops = "2000"; + maxRadius = "125"; + locked = "true"; + }; + + MissionCleanup.add(%Ash); + + %Ash.schedule(20000, "delete"); + + +} + +function CmndMessageAll(%mes) +{ + messageAll('ALLMsg', %mes); +} + +function NukeImage::onFire(%data, %obj, %slot) +{ + %vector = %obj.getMuzzleVector(%slot); + %x = (getRandom() - 0.0) * 1 * 1 * %data.projectileSpread; + %y = (getRandom() - 0.0) * 1 * 1 * %data.projectileSpread; + %z = (getRandom() - 0.0) * 1 * 1 * %data.projectileSpread; + %mat = MatrixCreateFromEuler(%x @ " " @ %y @ " " @ %z); + %vector = MatrixMulVector(%mat, %vector); + + %p = new (%data.projectileType)() { + dataBlock = %data.projectile; + initialDirection = %vector; + initialPosition = %obj.getMuzzlePoint(%slot); + sourceObject = %obj; + sourceSlot = %slot; + }; + MissionCleanup.add(%p); + %obj.lastProjectile = %p; + %client.projectile = %p; + + +} + +function NukeImage::onMount(%data, %obj, %node) +{ + Parent::onMount(%data, %obj, %node); + %p = new TargetProjectile(){ + dataBlock = NukeTargeterBeam; + initialDirection = %obj.getMuzzleVector(%slot); + initialPosition = %obj.getMuzzlePoint(%slot); + sourceObject = %obj; + sourceSlot = %slot; + vehicleObject = %vehicle; + }; + MissionCleanup.add(%p); + %p.setTarget(%obj.team); + %obj.NukeTargBeam = %p; + + Parent::onMount(%this, %obj, %slot); + commandToClient( %obj.client, 'BottomPrint', "Project Uber: Planetary Cannon Edition", 5, 2); +} + +function NukeImage::onUnmount(%data, %obj, %node) +{ + if(isObject(%obj.NukeTargBeam)) + %obj.NukeTargBeam.delete(); + Parent::onUnmount(%data, %obj, %node); +} +//thanks to The_Force for these 2 functions +function BigFatNukeTarget(%pos) +{ + echo("nuke target position: " @ %pos); + %mainUpPos = vectoradd(%pos, "0 0 1000");// 1000m up + + %lasePos1 = vectoradd(%mainUpPos, "1000 0 0"); + %laseVec1 = VectorAdd(%pos, VectorScale(%lasePos1, -1)); + //%laseVec1 = VectorNormalize(%laseVec1); + %laser1 = new TargetProjectile() + { + dataBlock = RedTargeterBeam; + initialDirection = %laseVec1; + initialPosition = %lasePos1; + }; + MissionCleanup.add(%laser1); + + %lasePos2 = vectoradd(%mainUpPos, "-1000 0 0"); + %laseVec2 = VectorAdd(%pos, VectorScale(%lasePos2, -1)); + //%laseVec2 = VectorNormalize(%lasePos2); + %laser2 = new TargetProjectile() + { + dataBlock = RedTargeterBeam; + initialDirection = %laseVec2; + initialPosition = %lasePos2; + }; + MissionCleanup.add(%laser2); + + %lasePos3 = vectoradd(%mainUpPos, "0 1000 0"); + %laseVec3 = VectorAdd(%pos, VectorScale(%lasePos3, -1)); + //%laseVec3 = VectorNormalize(%laseVec3); + %laser3 = new TargetProjectile() + { + dataBlock = RedTargeterBeam; + initialDirection = %laseVec3; + initialPosition = %lasePos3; + }; + MissionCleanup.add(%laser3); + + %lasePos4 = vectoradd(%mainUpPos, "0 -1000 0"); + %laseVec4 = VectorAdd(%pos, VectorScale(%lasePos4, -1)); + //%laseVec4 = VectorNormalize(%laseVec4); + %laser4 = new TargetProjectile() + { + dataBlock = RedTargeterBeam; + initialDirection = %laseVec4; + initialPosition = %lasePos4; + }; + MissionCleanup.add(%laser4); + + %client = %obj.sourceObject.client; + messageAll("", "\c2A Planetary Cannon has been targeted!"); + messageAll("", "\c2Planetary Cannon fires in 1:00 min.~wfx/misc/red_alert.wav"); + + schedule(30000,0, "CmndMessageAll", '\c2Planetary Cannon fires in 30 seconds.~wfx/misc/hunters_30.wav'); + schedule(50000,0, "CmndMessageAll", '\c2Planetary Cannon fires in 10 seconds.~wfx/misc/hunters_10.wav'); + schedule(55000,0, "CmndMessageAll", '\c2Planetary Cannon fires in 5 seconds.~wfx/misc/hunters_5.wav'); + schedule(56000,0, "CmndMessageAll", '\c2Planetary Cannon fires in 4 seconds.~wfx/misc/hunters_4.wav'); + schedule(57000,0, "CmndMessageAll", '\c2Planetary Cannon fires in 3 seconds.~wfx/misc/hunters_3.wav'); + schedule(58000,0, "CmndMessageAll", '\c2Planetary Cannon fires in 2 seconds.~wfx/misc/hunters_2.wav'); + schedule(59000,0, "CmndMessageAll", '\c2Planetary Cannon fires in 1 second.~wfx/misc/hunters_1.wav'); + schedule(60000,0, "CmndMessageAll", '\c2The Planetary Cannon has fired!'); + + %laser1.schedule(61.5 * 1000, "delete");// Delete all the lasers after 1 min, 5 sec. + %laser2.schedule(61.5 * 1000, "delete"); + %laser3.schedule(61.5 * 1000, "delete"); + %laser4.schedule(61.5 * 1000, "delete"); + + schedule(60 * 1000, 0, BigFatNukeDrop, %mainUpPos); +} + +function BigFatNukeDrop(%pos) +{ + + echo("nuke target position: " @ %pos); + %mainUpPos = vectoradd(%pos, "0 0 1000");// 1000m up + + %BigFatNuke = new LinearFlareProjectile() + { + dataBlock = NukeBolt; + initialPosition = %mainUpPos; + initialDirection = "0 0 -1"; + }; + MissionCleanup.add(%BigFatNuke); + + %alertPos = VectorAdd(%pos, "0 0 1000");// Meters from the target pos. + %nukeAlert = new WayPoint() + { + position = %alertPos; + rotation = "1 0 0 0"; + scale = "1 1 1"; + name = "Incoming Cannon Blast"; + dataBlock = "WayPointMarker"; + lockCount = "0"; + homingCount = "0"; + }; + MissionCleanup.add(%nukeAlert); + + %nukeAlert.schedule(5 * 1000, "delete"); // Delte the warning way point after 5 seconds. + centerPrintAll("Incoming Planetary Cannon Blast! Get your ass under cover!", 4, 2); + messageAll('',"~wfx/misc/red_alert.wav");// Alarm Sound +} + +function TargeterShot::onExplode(%data, %proj, %pos, %mod) +{ +BigFatNukeTarget(%pos); +} + +function GameConnection::Givepce(%cl) +{ +%cl.player.MountImage(NukeImage,0); +} + + + +function nukewind(%pos,%start,%maxrad,%lastar) +{ + +%rad = nukerad(%start); + +nukewindset(%pos, %rad,%lastar); +%lastar = %rad; +if (%rad < %maxrad) + schedule(500,0,"nukewind",%pos,%start,%maxrad,%lastar); +} + +function nukewindset(%pos, %area,%lastar) +{ +if (%area > 2000) + %area = 2000; + + InitContainerRadiusSearch(%pos, %area, $TypeMasks::VehicleObjectType | $TypeMasks::PlayerObjectType |$TypeMasks::StaticShapeObjectType| $TypeMasks::ItemObjectType | $TypeMasks::CorpseObjectType); // ); + + %numTargets = 0; + while ((%targetObject = containerSearchNext()) != 0) + { + %dist = containerSearchCurrRadDamageDist(); + + if (%dist > %area) + continue; + + %targets[%numTargets] = %targetObject; + %targetDists[%numTargets] = %dist; + %numTargets++; + } + + for (%i = 0; %i < %numTargets; %i++) + { + %targetObject = %targets[%i]; + %dist = %targetDists[%i]; + %distPct = %dist / %area; + + %coverage = calcExplosionCoverage(%pos, %targetObject, + ($TypeMasks::InteriorObjectType | + $TypeMasks::TerrainObjectType | + $TypeMasks::ForceFieldObjectType)); + if (%coverage == 0) + continue; + + if (%area < 500) + %power = %area; + else + %power = Limit(500 - %area,0,200); + + if (%dist > %lastar) //Shockwave + { + %force = (%power/100)*%targetobject.getDatablock().mass; + %damage = Limit(100/%dist,0,100); + %upvec = "0 0 1"; + } + else + { + %force = 0; + %damage = Limit(5/%dist,0,100); + %upvec = ""; + } + + %tgtPos = %targetObject.getWorldBoxCenter(); + %vec = VectorNormalize(VectorAdd(vectorNeg(vectorNormalize(vectorSub(%pos, %tgtPos))),%upvec)); + %nForce = %force * %distPct * 10; + %forceVector = vectorScale(%vec, %nForce); + + if(!%targetObject.inertialDampener && !%targetObject.getDatablock().forceSensitive) + %targetObject.applyImpulse(pos( %targetObject), %forceVector); + if (%damage>0.01) + %targetObject.getDataBlock().damageObject( %targetObject, 0,pos( %targetObject),%damage,$DamageType::Explosion); + } +} + + +function nukerad(%start) +{ +%seconds = (GetSimTime()-%start)/1000; +%rad = %seconds * 200 + Mpow(%seconds,2)*1; +return %rad; +} diff --git a/scripts/MTC_ai.cs b/scripts/MTC_ai.cs new file mode 100644 index 0000000..77e4027 --- /dev/null +++ b/scripts/MTC_ai.cs @@ -0,0 +1,1227 @@ +$MtcSuperRange = 0; + +$MtcMaxAmmo["flare","light"] = 8; +$MtcMaxAmmo["flare","medium"] = 10; +$MtcMaxAmmo["flare","heavy"] = 0; +$MtcMaxAmmo["flash","light"] = 5; +$MtcMaxAmmo["flash","medium"] = 8; +$MtcMaxAmmo["flash","heavy"] = 0; +$MtcMaxAmmo["cloak","light"] = 160; +$MtcMaxAmmo["cloak","medium"] = 120; +$MtcMaxAmmo["cloak","heavy"] = 0; +$MtcMaxAmmo["mine","light"] = 4; +$MtcMaxAmmo["mine","medium"] = 6; +$MtcMaxAmmo["mine","heavy"] = 20; + +$MtcDamageRun["light"] = 0.5; +$MtcDamageRun["medium"] = 0.55; +$MtcDamageRun["heavy"] = 0.75; + +///////////////////////////////////////////// +///////////////[[Part1]]///////////////////// +///////////////////////////////////////////// + +//Initialisation runs + +function Item::Initialize(%obj) +{ +//echo("Initialize"); +///Arm ourselfes if we need to. +if (!IsObject(%obj.turret) || %obj.weapon $= "") + %obj.Arm(); + +//Starting supplies +%size = $mtcWeaponSize[%obj.weapon]; + +%obj.ammo["mine"] = $MtcMaxAmmo["mine",%size] * getRandom(); +%obj.ammo["Cloak"] =$MtcMaxAmmo["cloak",%size] * getRandom(); +%obj.ammo["flare"] =$MtcMaxAmmo["flare",%size] * getRandom(); +%obj.ammo["flash"] =$MtcMaxAmmo["flash",%size] * getRandom(); + +//Set best attack patern + %obj.SetPatern(); + +//Set inventory loop +if (!%obj.invloop) + %obj.invloop(); + +//Set orders and run them + %obj.evaluate(); +} + + +function Item::SetPatern(%obj) +{ +//echo("setPatern"); +/// +/// sensors //// static /// turret /// gen +/// +%obj.maxdist = 500; //Standart set for now +%obj.noacloak = 1; //Standart off +%obj.nocloak = 0; + +if ($mtcWeaponSize[%obj.weapon] $= "light") + { + + } +else if ($mtcWeaponSize[%obj.weapon] $= "medium") + { + %obj.movemod = -0.25; + } +else if ($mtcWeaponSize[%obj.weapon] $= "heavy") + { + %obj.nofly = 1; + %obj.movemod = 0.5; + %obj.nocloak = 1; + } + + +if (%obj.weapon $= "chain") + { + %obj.patern = "attack"; + %obj.mindist = 20; + %obj.meddist = 50; + %obj.preftargets = "nturret lsensor ustatic astatic"; + %obj.preftargetslack = 100; + } +else if (%obj.weapon $= "plasma") + { + %obj.patern = "attack"; + %obj.mindist = 5; + %obj.meddist = 50; + %obj.preftargets = "lsensor lturret ustatic"; + %obj.preftargetslack = 50; + %obj.movemod = -0.25; + %obj.noacloak = 0; + } +else if (%obj.weapon $= "Fusion") + { + %obj.patern = "attack"; + %obj.mindist = 20; + %obj.meddist = 80; + %obj.preftargets = "agen astatic aturret"; + %obj.preftargetslack = 150; + } +else if (%obj.weapon $= "nerf") + { + %obj.patern = "attack"; + %obj.mindist = 5; + %obj.meddist = 20; + %obj.preftargets = "aplayer"; + %obj.preftargetslack = 200; + } +else if (%obj.weapon $= "disc") + { + %obj.patern = "attack"; + %obj.mindist = 15; + %obj.meddist = 200; + %obj.preftargets = "nturret lsensor aplayer"; + %obj.preftargetslack = 50; + } +else if (%obj.weapon $= "blaster") + { + %obj.patern = "attack"; + %obj.mindist = 5; + %obj.meddist = 50; + %obj.preftargets = "lsensor lturret nturret agen"; + %obj.preftargetslack = 50; + %obj.noacloak = 0; + } +else if (%obj.weapon $= "target") + { + %obj.patern = "range"; + %obj.mindist = 25; + %obj.meddist = 200; + %obj.preftargets = "aturret agen"; + %obj.preftargetslack = 50; + + } +else if (%obj.weapon $= "grenade") + { + %obj.patern = "range"; + %obj.mindist = 30; + %obj.meddist = 200; + %obj.preftargets = "ustatic lsensor agen"; + %obj.preftargetslack = 50; + } +else if (%obj.weapon $= "laser") + { + %obj.patern = "range"; + %obj.mindist = 20; + %obj.meddist = 200; + %obj.preftargets = "aplayer lsensor"; + %obj.preftargetslack = 50; + } +else if (%obj.weapon $= "missile") + { + %obj.patern = "range"; + %obj.mindist = 50; + %obj.meddist = 200; + %obj.preftargets = "aturret aplayer avehicle"; + %obj.preftargetslack = 75; + } +else if (%obj.weapon $= "swarmdisc") + { + %obj.patern = "range"; + %obj.mindist = 50; + %obj.meddist = 200; + %obj.preftargets = "aturret aplayer avehicle"; + %obj.preftargetslack = 75; + } +else if (%obj.weapon $= "ionmissile") + { + %obj.patern = "range"; + %obj.mindist = 100; + %obj.meddist = 200; + %obj.preftargets = "pstatic pturret pgen"; + %obj.preftargetslack = 1000; + } +else if (%obj.weapon $= "ionbeam") + { + %obj.patern = "range"; + %obj.mindist = 50; + %obj.meddist = 200; + %obj.preftargets = "pstatic pturret pgen"; + %obj.preftargetslack = 1000; + } +else if (%obj.weapon $= "mortar") + { + %obj.patern = "range"; + %obj.mindist = 50; + %obj.meddist = 300; + %obj.preftargets = "agen astatic aturret"; + %obj.preftargetslack = 50; + } +else if (%obj.weapon $= "tractor") + { + %obj.patern = "range"; + %obj.mindist = 50; + %obj.meddist = 100; + %obj.preftargets = "aplayer avehicle"; + %obj.preftargetslack = 500; + } +else + { + %obj.patern = "attack"; + %obj.mindist = 5; + %obj.meddist = 20; + %obj.preftargets = "aplayer"; + %obj.preftargetslack = 50; + } +} + +///////////////////////////////////////////// +///////////////[[Part2]]///////////////////// +///////////////////////////////////////////// + +//Loops + +function Item::invloop(%obj) +{ +//echo("invloop"); +Cancel(%obj.invloop); + +if (!%obj.nosuply) + { + %size = $mtcWeaponSize[%obj.weapon]; + %obj.ammo["mine"] = limit(%obj.ammo["mine"] + 1,0, $MtcMaxAmmo["mine",%size]); + %obj.ammo["cloak"] = limit(%obj.ammo["cloak"] + 30,0, $MtcMaxAmmo["cloak",%size]); + %obj.ammo["flare"] = limit(%obj.ammo["flare"] + 1,0, $MtcMaxAmmo["flare",%size]); + %obj.ammo["flash"] = limit(%obj.ammo["flash"] + 1,0, $MtcMaxAmmo["flash",%size]); + } + +if (!%obj.noaggression) + %obj.aggression = limit(%obj.aggression + getRandom()-0.5,0,10); + +%obj.notify("ammo"); + +//Gets his stuff every minute. +%obj.invloop = %obj.schedule(60000,"invloop"); +} + +function Item::evaluate(%obj) +{ +%obj.lastevaltime = getSimTime(); +Cancel(%obj.evalloop); + +%obj.sound("think"); + +if (%obj.order !$= "") + { + //Attack + if (%obj.order $= "attack") + { + if (%obj.ValidTarget() || %obj.targetrun < 6) + { + %obj.targetrun++; + ///LETS GO ATTACK + %obj.attackrun(); //Only attack the same target for 1 minute + %obj.notify("attack"); + } + else + { + %obj.target = %obj.NewTarget(); + if (%obj.ValidTarget()) + { + ///STOP ATTACKING + %obj.order = ""; + } + else + { + //Go attack the next run + %obj.targetrun = ""; + } + } + } + + //Flee + else if (%obj.order $= "flee") + { + if (%target = %obj.gotThreat() !$= "") + { + ///LETS GO FLEE + %obj.target = %target; + %obj.fleerun(); + %obj.notify("flee"); + } + else + { + //STOP FLEEING + %obj.order = ""; + } + } + + //Roam + else if (%obj.order $= "roam") + { + //Still no valid target? + %target = %obj.ClosestTarget(); + if (!%obj.ValidTarget(%obj.NewTarget())) + { + ///LETS GO ROAM + //%obj.target = %target; + %obj.roamrun(); + %obj.notify("roam"); + } + else + { + ///STOP ROAMING + %obj.order = ""; + } + } + //Repair + else if (%obj.order $= "repair") + { + //Are we still damaged? + if (%obj.turret.getDamagePct() > 0.1) + { + //Are there enemies nearby? + if (%obj.gotThreat()) + { + if (%obj.needflee()) + { + //STOP REPAIRING + %obj.order = ""; + } + else + { + //STOP REPAIRING + %obj.order = ""; + } + } + else + { + ///LETS GO REPAIR + %obj.repairrun(); + %obj.notify("repair"); + } + } + else + { + ///STOP REPAIRING + %obj.order = ""; + } + } + } + +///So we didn't have any orders? + +if (%obj.order $= "") + { + ///Are we hurt?? + if (%obj.needflee()) + { + ///Do we need to run? + if (%obj.gotThreat()) + { + %obj.order = "flee"; + %rechecktime = 450; + Cancel(%obj.mainrun); + } + else + { + %obj.order = "repair"; + %rechecktime = 450; + Cancel(%obj.mainrun); + } + } + else + { + ///Anyone to attack? + %obj.target = %obj.NewTarget(); + if (!%obj.ValidTarget()) + { + %obj.target= %obj.closestTarget(); + %obj.order = "roam"; + %rechecktime = 450; + Cancel(%obj.mainrun); + } + else + { + %obj.order = "attack"; + %rechecktime = 450; + Cancel(%obj.mainrun); + } + } + } + +if (!%rechecktime) + %rechecktime = 10000; + +%obj.evalloop = %obj.schedule(%rechecktime,"evaluate"); +} + +function Item::Needflee(%obj) +{ +%size = $mtcWeaponSize[%obj.weapon]; +if (%obj.turret.getDamagePct() > $MtcDamageRun[%size]) + return 1; +else if (%obj.ammo["flare"] < $MtcDamageRun[%size]*$MtcMaxAmmo["flare",%size] && $MtcMaxAmmo["flare",%size]) + return 1; +return 0; +} + +///////////////////////////////////////////// +///////////////[[Part3]]///////////////////// +///////////////////////////////////////////// + +//Targeting + +// Defined in scripts/ion.cs +//function GameBase::isEnemy(%obj,%target) { +// //echo("isenemy"); +// if (!isObject(%obj) || !isObject(%target)) +// return ""; +// if (%obj.team != %target.team) ///Other teams default to enemy. +// return 1; +// if (%obj.getOwner().evil) { +// if (%obj.getOwner() != %target.client && %obj.getOwner() != %target.getOwner()) +// return 1; +// } +// return ""; +//} + +function Item::gotThreat(%obj) //////Needs update. +{ +//echo("gotThreat"); +%target = closestTarget(%obj.getWorldboxCenter(),"aplayer pturret cvehile",%obj.maxdist,%obj); +if (GetWord(%target,1) < %obj.maxdist) + return GetWord(%target,0); +return ""; +} + +function Item::ValidTarget(%obj,%target) ///Needs update +{ +if (!%target) + %target = %obj.target; + +if (mtcCleantarget(%target)) + { + if (%target == %obj.forcetarget()) + return 1; + + if (%obj.terdist(%target) < %obj.maxdist) + { + if (!(%target.getDataBlock().className $= "Armor" && %target.getState() $= "Dead")) + { + return 1; + } + } + } +return ""; +} + +//Can we as mtc get to this target? +function mtcCleantarget(%target) +{ +//echo("mtcCleantarget"); + //Only exsistant objects, no clients. + //No nonpowered forcefields. + //Only players,vehicles or stuff deployed ingame. + //Only stuff outside buildings or that sticks out. + +%group = nameToID("MissionCleanup/Deployables"); +if (%target && IsObject(%target) && !%target.player) + { + if (!(!%target.isPowered() && %target.isforcefield())) + { + if (%target.getType() & typelist("aplayer avehicle") || %group.isMember(%target)) + { + %fstat = aboveground(%target.getworldboxcenter(),1,%obj); + %stat = GetWord(%fstat,0); + if(%stat $= "open" || %stat $= "roof" || %stat $= "shadow") + return 1; + else if (%target.seetop()) + return 1; + } + } + } +return ""; +} + +function Item::NewTarget(%obj,%target) +{ +//echo("NewTarget"); +if (%obj.forcetarget()) + return %obj.forcetarget(); + +%sugtarget = %target; + +if (Change(%obj.aggression,5,10) && IsObject(%plyrtarget)) + { + %target = closestTarget(%obj.getWorldboxCenter(),"aplayer cvehile","",%obj); + } + else + { + %preftarget = closestTarget(%obj.getWorldboxCenter(),%obj.preftargets,"",%obj); + %alttarget = closestTarget(%obj.getWorldboxCenter(),"aall","",%obj); + if (GetWord(%alttarget,1) > GetWord(%preftarget,1)- %obj.preftargetslack && IsObject(%preftarget)) + { + %target = %preftarget; + } + else + { + %target = %alttarget; + } + } +if (!IsObject(%target)) + %target = ClosestPlayer(%obj.getWorldBoxCenter(),"","",%obj); + +return getWord(%target,0); +} + +function Item::ClosestTarget(%obj) +{ +//echo("closesttarget"); +return closestTarget(%obj.getWorldBoxCenter(),"aall","",%obj); +} + +function closestTarget(%location,%ftype,%range,%obj) +{ +//echo("closesttarget"); +%group = nameToID("MissionCleanup/Deployables"); + +if (%ftype $= "") + %ftype = aall; +if (!%range) + %range = 1000 + (100000* $MtcSuperRange); + +%mask = typelist(%ftype); + + +InitContainerRadiusSearch(%location,%range,%mask); + + while ((%target = ContainerSearchNext()) != 0) + { + if (mtcCleantarget(%target)) + { + if (%target.onpreflist(%ftype) && (IsObject(%obj) && %obj.isEnemy(%target))) + return %target SPC containerSearchCurrRadDamageDist(); + } + + } + +return ""; +} + + +function Item::forcetarget(%obj) +{ +//echo("forcetarget"); +%target = %obj.forcetarget; +if (%target !$= "") + { + if (IsObject(%target.player)) + return %target.player; + else if (%target.getClassname() !$= "GameConnection") + return %target; + } +%target = mtcgroup.forcetarget; +if (%target !$= "") + { + if (IsObject(%target.player)) + return %target.player; + else if (%target.getClassname() !$= "GameConnection") + return %target; + } +return ""; +} + +///////////////////////////////////////////// +///////////////[[Part4]]///////////////////// +///////////////////////////////////////////// + +//Actions + +function Item::resetorders(%obj) +{ +//echo("resetorders"); + %obj.order = ""; + Cancel(%obj.evalloop); + %obj.evalloop = %obj.schedule(450,"evaluate"); + return""; +} + +//GO ATTACK +function Item::attackrun(%obj) +{ +//echo("attackrun"); +Cancel(%obj.mainrun); + +%obj.checkflare(); +%obj.flaredelay(1); + +if (!%obj.ValidTarget() || %obj.needflee()) + { + return %obj.resetorders(); + } + +///Basic Information +%loc = %obj.getWorldboxCenter(); +%target = %obj.target; +%tloc = %obj.target.getWorldboxCenter(); +%line = VectorSub(%tloc,%loc); +%dir = VectorNormalize(%line); +%dist = VectorLen(%line); + +///Movement patern +%obj.attackcloak = 0; +%obj.canfire("target"); + +if (%dist < %obj.mindist && !(%obj.forcetarget() && !%obj.nofly)) + { + ///Whoa we're too close + %obj.move(%tloc,"to",-0.6); + %obj.dodge = randomlev(); + } +else if (%dist > %obj.mindist && %dist < %obj.meddist && !(%obj.forcetarget() && !%obj.nofly)) + { + //perfect let's Guooo. + if (%obj.patern $= "attack") + { + ///Lets make him dizzy + %obj.move(%tloc,"side",%obj.dodge*0.5); + + } + else if (%obj.patern $= "range") + { + ///Lets get a nice high spot + %obj.move(%tloc,"up",1); + } + else + { + ///Oh sure.. I'l be dead in the water. + } + } +else if ((%dist > %objmeddist && %dist < %obj.maxdist) || (%obj.forcetarget() && !%obj.nofly)) + { + //Damn he's too far + %obj.move(%tloc,"to",0.9); + %obj.dodge = randomlev(); + if ((!%obj.noacloak) && !%obj.forcetarget() && %dist > %obj.meddist*1.2) + { + %obj.attackcloak = 1; + %obj.cloak(1); + } + } +else + { + //We're outa range. + %obj.move(%tloc,"to",0.5); + %obj.canfire(); + if (!%obj.noacloak) + { + %obj.attackcloak = 1; + %obj.cloak(1); + } + } + +if (!%obj.attackcloak) + %obj.cloak(); + +%obj.mainrun = %obj.schedule(500, "attackrun"); +} + +//GO FLEE + +function Item::fleerun(%obj) +{ +//echo("fleerun"); +Cancel(%obj.mainrun); + +%obj.checkflare(); +%obj.flaredelay(); + +if (%target = %obj.gotThreat()) + %obj.target = %target; +else if (%target = %obj.closestTarget()) + %obj.target = %target; +else + { + //Omg there's noone near for miles + return %obj.resetorders(); + } + +///Basic Information +%loc = %obj.getWorldboxCenter(); +%target = %obj.target; +%tloc = %obj.target.getWorldboxCenter(); +%line = VectorSub(%tloc,%loc); +%dir = VectorNormalize(%line); +%dist = VectorLen(%line); + +///Movement patern + %obj.canfire(); + +if (%dist < %obj.mindist) + { + //Whoa double time + %obj.move(%tloc,"to",-1.2); + %obj.cloak(1); + if (!%obj.cloaked) + %obj.canfire("target"); + } +else if (%dist > %obj.mindst && %dist < %obj.meddist ) + { + //Move move move + %obj.move(%tloc,"to",-1); + %obj.cloak(1); + %obj.Mine(); + if (!%obj.cloaked) + %obj.canfire("target"); + } +else if (%dist > %objmeddist && %dist < %obj.maxdist ) + { + //Just a litle futher + %obj.target = %obj.closesttarget(); + %obj.move(%tloc,"to",-0.8); + %obj.cloak(1); + } +else + { + %obj.target = %obj.closesttarget(); + //Finally he's gone. + %obj.cloak(0); + } +%obj.mainrun = %obj.schedule(500, "fleerun"); +} + +//GO REPAIR + +function Item::repairrun(%obj) +{ +//echo("repairrun"); +Cancel(%obj.mainrun); +Cancel(%obj.repairsch); + +%obj.checkflare(); +%obj.flaredelay(); + +if (%obj.gotThreat()) + { + return %obj.resetorders(); + } + + +%obj.cloak(1); +%obj.canfire(); + +createLifeEmitter(%obj.getWorldboxCenter(), ELFSparksEmitter, 450); + +%size = $mtcWeaponSize[%obj.weapon]; +%obj.ammo["flare"] = limit(%obj.ammo["flare"] + 1,0,$MtcMaxAmmo["flare",%size]); + +%obj.turret.setRepairRate(0.004); +%obj.repairsch = %obj.turret.schedule(450,"setRepairRate",0); + +%obj.mainrun = %obj.schedule(500,"repairrun"); +} + +//GO ROAM + +function Item::roamrun(%obj) +{ +//echo("roamrun"); +Cancel(%obj.mainrun); + +%obj.roamtime = %obj.roamtime - 1; + +//%obj.target = %obj.NewTarget(); +//%obj.ValidTarget() +if ( %obj.needflee()) + { + return %obj.resetorders(); + } + + +%obj.checkflare(); +%obj.flaredelay(); + +if (%obj.roamtime < 0) + { + %obj.totalroam++; + %obj.roamdir = getRandom(); + %obj.roamtime = getRandom() * 200+50; + if (%obj.totalroam > 20) + { + %obj.totalroam = 0; + %obj.telleport(getTerrainHeight2("0 0 0","0 0 -1")); + } + } + +%obj.cloak(); +%obj.canfire(); + +///This will make the mtc move directly towards the closest target when he's angry +///And all directions when he's not. +if (IsObject(%obj.target) && %obj.dist(%obj.target) < %obj.maxdist) + %obj.moveangle = RandomLev()*($Pi + $Pi*getRandom()); +else + %obj.moveangle = %obj.roamdir*(((1-(%obj.aggression /10))* 2* $Pi) - $Pi); + +if (MtcCleanTarget(%obj.target)) + { + %location = %obj.target.getWorldBoxCenter(); + if ((%obj.dist(%obj.target)/%obj.altdist(%obj.target))<1.5) + %obj.moveangle = 0; + } +else + { + %location = VectorAdd(mCos(%obj.Moveangle)*100 SPC mSin(%obj.moveangle)*100 SPC 0,%obj.getWorldBoxCenter()); + } + +%obj.move(%location,"angle",0.8); + +%obj.mainrun = %obj.schedule(500, "roamrun"); +} + + +//Go Move Target (avioding threats) + +function Item::moveTrun(%obj) +{ +//echo("moverun"); +Cancel(%obj.mainrun); + +%obj.checkflare(); + +if (!mtcCleanTarget(%obj.target)) + { + %obj.order = ""; + Cancel(%obj.evalloop); + %obj.evalloop = %obj.schedule(450,"evaluate"); + } + +///Basic Information +%loc = %obj.getWorldboxCenter(); +%target = %obj.target; +%tloc = %obj.target.getWorldboxCenter(); +%line = VectorSub(%tloc,%loc); +%dir = VectorNormalize(%line); +%dist = VectorLen(%line); + +if (%threat = %obj.gotThreat()) + { + %trloc = %Threat.getWorldBoxCenter(); + %trdir = %obj.dir(%threat); + %angle = VectorAngle(%trdir,%dir); + %avoiddir = VectorCross(VectorCross(%trdir,%dir),%trdir); + } + +%obj.canfire(""); + +if (%dist < %obj.mindist) + { + %obj.order = ""; + Cancel(%obj.evalloop); + %obj.evalloop = %obj.schedule(450,"evaluate"); + } +else + { + if (%angle > $Pi) + %obj.move(%tloc,"to",1); + else + { + %obj.movedir = %avoiddir; + %obj.move(%trloc,"dir",1); + } + } + + +%obj.mainrun = %obj.schedule(500, "moveTrun"); +} + +//Basic Moving +function Item::move(%obj,%location,%mdir,%speed) +{ +//echo("move"); +if (%obj.nomove) +return ""; + +%obj.evalpos++; + +//Information + +%selfloc = %obj.getWorldBoxCenter(); +%targetloc = %location; +%targetline = Vectorsub(%targetloc,%selfloc); +%targetdir = VectorNormalize(%targetline); +%targetdist = VectorLen(%targetline); +%altdist = GetWord(%targetline,2); + + +if (%obj.evalpos > 10) + { + %obj.FixHeight(); + + %movedist = VectorDist(%obj.getWorldboxCenter(),%obj.lastlocation); + + if ((%movedist < 5 && %mdir !$= "up" && %targetdist > %obj.meddist) || (%movedist < 1 && %targetdist > %obj.mindist) || %movedist < 0.1) + { + %obj.freeforce = %obj.freeforce + 10; + if (%obj.freeforce * %speed < %targetdist) + %dir = VectorScale(%targetdir,%obj.freeforce*%speed); + else + %dir = VectorScale(%targetdir,%targetdist - 2); + + %newpos = getTerrainHeight2(VectorAdd(%obj.getWorldboxCenter(),%dir),"0 0 -1"); + %obj.telleport(%newpos); //Break free. + %obj.movepower = 60; + } + else if (%movedist < 20) + { + %obj.movepower = Limit(%obj.movepower+20,0,1000); + %obj.freeforce = 10; + } + else + { + %obj.movepower = 60; + %obj.freeforce = 10; + } + + %obj.lastlocation = %obj.getWorldboxCenter(); + %obj.evalpos = 0; + } + + + +if (%targetdist > 2000 && %obj.order !$= "roam") + { + %dir = VectorScale(%targetdir,%targetdist-500); + %newpos = VectorAdd(%obj.getWorldboxCenter(),%dir); + if ((%targetdist/%altdist)>1.5) + %newpos = getTerrainHeight2(%newpos,"0 0 -1"); + %obj.telleport(%newpos); //Get way closer. + } +else if (%targetdist > 4000 && %obj.order $= "roam" && %disabled) + { + %dir = VectorScale(%targetdir,%targetdist-3000); + %newpos = VectorAdd(%obj.getWorldboxCenter(),%dir); + if ((%targetdist/%altdist)>1.5) + %newpos = getTerrainHeight2(%newpos,"0 0 -1"); + %obj.telleport(%newpos); //Get some closer. + } + + +%offset = VectorScale(VectorCross(VectorCross("0 0 1",%targetdir),%targetdir),20); + +%res = containerRayCast(%obj.getWorldboxCenter(), VectorAdd(%obj.getWorldboxCenter(),%offset), $TypeMasks::TerrainObjectType, %obj.turret); + + +if (%res) + { + %nrm = normalFromRaycast(%res); + } +else + { + %nrm = "0 0 1"; + } + +%dir = %targetdir; +if (%mdir $= "to") // Towards/from + %movedir = VectorCross(VectorCross(%nrm,%dir),%nrm); + +else if (%mdir $= "side") //Sideways + %movedir = VectorCross(%nrm,%dir); + +else if (%mdir $= "up") //Up the mountain + { + if (vAbs(floorvec(%nrm,100)) $= "0 0 1") + %movedir = VectorCross(%nrm,%dir); + else + %movedir = VectorCross(VectorCross(%nrm,"0 0 1"),%nrm); + } + +else if (%mdir $= "angle") //Certain angle away from target. + { + %movedir1 = VectorScale(VectorCross(VectorCross(%nrm,%dir),%nrm),MCos(%obj.moveangle)); + %movedir2 = VectorScale(VectorCross(%nrm,%dir),MSin(%obj.moveangle)); + %movedir = VectorAdd(%movedir1,%movedir2); + } +else if (%mdir $= "dir") + { + %movedir = VectorCross(VectorCross(%nrm,%obj.movedir),%nrm); + } + +//Flying + +%targetplace = GetWord(aboveground(%targetloc,1,0),0); +if (((%obj.wasflying && (%targetdist/%altdist)<2)|| %obj.forcetarget() || ((%targetdist/%altdist)<1.5 && %targetdist > 200)) && %obj.order $= "attack" && !%obj.nofly && (%targetplace $= "open"|| %targetplace $="roof")) + { + %speed = mCeil(%targetdist/100)+0.5; + %nrm = "0 0 1"; + %movedir = VectorNormalize(VectorAdd(VectorAdd(VectorCross(VectorCross(%nrm,%dir),%nrm),VectorCross(%nrm,%dir)),"0 0" SPC Lev(GetWord(%targetdir,2))/2)); + %obj.wasflying = 1; + %obj.flaredelay(1); + } +else if (VectorDist(getTerrainHeight2(pos(%obj),"0 0 -1"),pos(%obj))>50) + %movedir = VectorAdd(%movedir,"0 0" SPC GetWord(%targetdir,2)); +else + %obj.wasflying = 0; + +%pulse = Limit(1 * %obj.movepower * %speed*(1+%obj.movemod),-1000,1000); + +//Floating +if (%disabled && Isobject(Water) ) + { + %surface = GetWords(pos(%obj),0,1) SPC (GetWord(Water.getTransform(),2)+GetWord(Water.getScale(),2))+2; + if ((GetWord(pos(%obj),2)-GetWord(%surface,2))<2) + { + %res2 = containerRayCast(%surface,pos(%obj),-1, %obj.turret); + ////echo(%res2.getClassname()); + if (%res2 && %res2.getClassname() $= "Waterblock") + { + //%movedir = VectorAdd(%movedir,"0 0" SPC GetWord(%targetdir,2)); + //%obj.setTransform(%surface); + ////echo("float"); + } + } + } + +%obj.sound("move"); +%obj.Jet(500); +%movedir = VectorNormalize(%movedir); + +%obj.applyImpulse(%obj.getWorldboxCenter(), VectorScale(%movedir,%pulse)); +//%obj.setRotation(fullrot("0 0 1",%movedir)); +} + +function Item::flaredelay(%obj,%set) +{ +if (%set) + %obj.flaredelay++; +else + %obj.flaredelay = 0; +} + +function Item::checkflare(%obj) +{ +//echo("checkflare"); +%size = $mtcWeaponSize[%obj.weapon]; + if (%size $= "heavy") + %obj.turret.signature.PointDefLaser(); + +else if (%obj.turret.signature.homingcount) + { + %delay = Limit(%obj.flaredelay,0,10)*getRandom()*1000+100; + if (getRandom(1)) + %obj.schedule(500+getRandom()*500+%delay,"flare"); + + } +} + + +function Item::FixHeight(%obj) +{ +//echo("fixheight"); +%pos = getTerrainHeight2(%obj.getWorldboxCenter(),"0 0 -1"); +if (GetWord(%obj.getWorldboxCenter(),2) < GetWord(%pos,2)) + { + %obj.telleport(%pos); + } +} + + + + +function Gamebase::hastag(%obj,%tag) +{ +//echo("hastag"); +//Sizes +if (%tag $= "l" || %tag $= "m" || %tag $= "h") + { + %maxdamage= %obj.getDatablock().maxdamage; + if (%tag $= "l" && %maxdamage <= 1) + return 1; + else if (%tag $= "m" && %maxdamage > 1) + return 1; + else if (%tag $= "h" && %maxdamage > 2) + return 1; + } +//Powered +else if (%tag $= "p" || %tag $= "n") + { + %power = %obj.isPowered(); + if (%tag $= "p" && %power) + return 1; + else if (%tag $= "n" && !%power) + return 1; + } +//Shielded +else if (%tag $= "s" || %tag $= "u") + { + %shield = (%obj.getDataBlock().isShielded == 1 && %obj.getEnergyLevel() > 0); + if (%tag $= "s" && %shield) + return 1; + if (%tag $= "u" && !%shield) + return 1; + } +//Controlled +else if (%tag $= "c" || %tag $= "e") + { + %Piloted = !((%obj.getType() & $TypeMasks::VehicleObjectType) || %obj.getPilot()); + if (%tag $= "c" && %piloted) + return 1; + if (%tag $= "e" && !%piloted) + return 1; + } +//Everything ;) +else if (%tag $= "a") + return 1; + +return ""; +} + +function gettype(%type) +{ +//echo("gettype"); +if (%type $= "turret") + return $TypeMasks::TurretObjectType; +else if (%type $= "sensor") + return $TypeMasks::SensorObjectType; +else if (%type $= "gen") + return $TypeMasks::GeneratorObjectType; +else if (%type $= "static") + return $TypeMasks::StaticShapeObjectType; +else if (%type $= "player") + return $TypeMasks::PlayerObjectType; +else if (%type $= "vehicle") + return $TypeMasks::VehicleObjectType; +else if (%type $= "forcefield") + return $TypeMasks::ForceFieldObjectType; +else if (%type $= "all") + return $TypeMasks::StaticShapeObjectType | $TypeMasks::PlayerObjectType | $TypeMasks::VehicleObjectType | $TypeMasks::ForceFieldObjectType; +else + return 0; +} + +function typelist(%ftype) +{ +//echo("typelist"); +for(%tt = 0; %tt< GetWordCount(%ftype); %tt++ ) + { + %part = getWord(%ftype,%tt); + %type = getSubStr(%part,1,strLen(%part)); + %list = %list | gettype(%type); + } +return %list; +} + +function Gamebase::onpreflist(%obj,%ftype) +{ +//echo("onpreftlist"); +for(%tt = 0; %tt< GetWordCount(%ftype); %tt++ ) + { + %part = getWord(%ftype,%tt); + %tag = getSubStr(%part,0,1); + %type = getSubStr(%part,1,strLen(%part)); + if (%obj.getType() & gettype(%type) && %obj.hastag(%tag)) + return 1; + } +return ""; +} + + +function AssesBase(%location) +{ +//echo("assesbase"); +InitContainerRadiusSearch(%location,200,-1); + + while ((%target = ContainerSearchNext()) != 0) + { + if (%target.getType() & $TypeMasks::TurretObjectType && %target.hastag("s")) + %turretCount++; + if (%target.getType() & $TypeMasks::InteriorObjectType) + %interiorCount++; + if (%target.getType() & $TypeMasks::StaticShapeObjectType) + { + %staticCount++; + %height = %height + GetWord(AboveGround(pos(%target),1),1); + } + if (%target.getType() & $TypeMasks::PlayerObjectType) + %playerCount++; + %count=%count++; + } +%height = %height/%staticCount; +//echo(%count); +//echo(%height); +//echo(%interiorcount); +//echo(%turretcount); +//echo(%staticCount); +//echo(%playercount); +} + +function Vehicle::getpilot(%obj) ///Needs update to remotecontroll +{ +%pilot = %obj.getMountNodeObject(0); +%client = %pilot.client; +return %client; +} + + +function Shapebase::dir(%obj,%target) +{ +%pos1 = %obj.getWorldboxCenter(); +%pos2 = %target.getWorldboxCenter(); +return VectorNormalize(VectorSub(%pos2,%pos1)); +} + +function Shapebase::dist(%obj,%target) +{ +%pos1 = %obj.getWorldboxCenter(); +%pos2 = %target.getWorldboxCenter(); +return VectorDist(%pos1,%pos2); +} +function Shapebase::terdist(%obj,%target) +{ +%pos1 = %obj.getWorldboxCenter(); +%pos2 = %target.getWorldboxCenter(); +return VectorDist(GetWords(%pos1,0,1),GetWords(%pos2,0,1)); +} + +function Shapebase::altdist(%obj,%target) +{ +%pos1 = %obj.getWorldboxCenter(); +%pos2 = %target.getWorldboxCenter(); +return VectorDist(GetWord(%pos1,2),GetWord(%pos2,2)); +} diff --git a/scripts/MTC_core.cs b/scripts/MTC_core.cs new file mode 100644 index 0000000..87559e3 --- /dev/null +++ b/scripts/MTC_core.cs @@ -0,0 +1,1482 @@ +// MTC core + +$MTC_Loaded = true; + +if ($Host::MTC::MTCMax < 1) + $Host::MTC::MTCMax = 5; +if ($Host::MTC::MTCMin $= "" || $Host::MTC::MTCMin > $Host::MTC::MTCMax) + $Host::MTC::MTCMin = 1; + +compile("scripts/MTC_weap.cs"); +exec("scripts/MTC_weap.cs"); +compile("scripts/MTC_eweap.cs"); +exec("scripts/MTC_eweap.cs"); +compile("scripts/MTC_ai.cs"); +exec("scripts/MTC_ai.cs"); +compile("scripts/MTC_level.cs"); +exec("scripts/MTC_level.cs"); + +//Plasma +$DeathMessageTurretKill[$DamageType::Plasma, 0] = '\c0%1 was vaporized by a rampaging plasma MTC.'; +$DeathMessageTurretKill[$DamageType::Plasma, 1] = '\c0%1 tried to dance with a plasma MTC but forgot to wear %3 dancing shoes.'; +$DeathMessageTurretKill[$DamageType::Plasma, 2] = '\c0%1 was searching for a place to settle down when a plasma MTC ran over %2.'; +//Chain +$DeathMessageTurretKill[$DamageType::Bullet, 0] = '\c0A misguided chain MTC thought %1 would look better perforated.'; +$DeathMessageTurretKill[$DamageType::Bullet, 1] = '\c0%1 got in the way of the wrath of an almighty chain MTC.'; +$DeathMessageTurretKill[$DamageType::Bullet, 2] = '\c0%1 couldn\'t dodge the 60 bullets per second a chain MTC threw at %2.'; +//laser +$DeathMessageTurretKill[$DamageType::Laser, 0] = '\c0%1 looked around the corner only to get %3 head burned of by a laser MTC.'; +$DeathMessageTurretKill[$DamageType::Laser, 1] = '\c0%1 forgot that the green beams where harmless, not the red ones.'; +$DeathMessageTurretKill[$DamageType::Laser, 2] = '\c0%1 wasn\'t faster than the speed of light and was shot by a laser MTC.'; +//grenade +$DeathMessageTurretKill[$DamageType::Grenade, 0] = '\c0%1 mistook a grenade MTC\'s rage for some harmless clouds.'; +$DeathMessageTurretKill[$DamageType::Grenade, 1] = '\c0%1 was buried under the wrath of a grenade MTC.'; +$DeathMessageTurretKill[$DamageType::Grenade, 2] = '\c0%1 still has to learn that you can\'t pick up grenades and trow them back in Tribes 2.'; +//Disc +$DeathMessageTurretKill[$DamageType::Disc, 0] = '\c0%1 dodged right into a disc MTC\'s spinfusor.'; +$DeathMessageTurretKill[$DamageType::Disc, 1] = '\c0%1 didn\'t notice the disc MTC that was sneaking up on %2 untill it was too late.'; +$DeathMessageTurretKill[$DamageType::Disc, 2] = '\c0%1 had an encounter with a disc MTC and didn\'t live to tell about it.'; +//Missile +$DeathMessageTurretKill[$DamageType::Missile, 0] = '\c0%1 forgot to drop a flare while running from a missle MTC\'s missile'; +$DeathMessageTurretKill[$DamageType::Missile, 1] = '\c0%1 didn\'t know a missile MTC had declared it no-flying day.'; +$DeathMessageTurretKill[$DamageType::Missile, 2] = '\c0%1 was gunned down by a missile MTC\'s mid-day express.'; +//Blaster +$DeathMessageTurretKill[$DamageType::Blaster, 0] = '\c0%1 was smacked down by a blaster MTC.'; +$DeathMessageTurretKill[$DamageType::Blaster, 1] = '\c0%1 fell down and was run over by a blaster MTC.'; +$DeathMessageTurretKill[$DamageType::Blaster, 2] = '\c0%1 had the bad luck of being spotted by a blaster MTC.'; +//Mortar +$DeathMessageTurretKill[$DamageType::Mortar, 0] = '\c0%1 never knew his limbs could fly in opposite directions until a mortar MTC showed him.'; +$DeathMessageTurretKill[$DamageType::Mortar, 1] = '\c0%1 was fused to the terrain by a mortar MTC.'; +$DeathMessageTurretKill[$DamageType::Mortar, 2] = '\c0%1 saw a MTC turret\'s green rain and forgot to get out of the way.'; + +$mtcBaseSize["light"] = "1.6 3 0.75"; +$mtcBaseSize["medium"] = "3 3.6 1.2"; +//$mtcBaseSize["light"] = "6 6 2"; +//$mtcBaseSize["medium"] = "6 10 1"; +$mtcBaseSize["heavy"] = "6 8 2"; + +$mtcTurretSize["light"] = "1.2 1.5 1.15"; +$mtcTurretSize["medium"] = "2.22 2.4 1.44"; +//$mtcTurretSize["light"] = "4 5 3"; +//$mtcTurretSize["medium"] = "1 1 0.75"; +$mtcTurretSize["heavy"] = "1 1 0.75"; + + +$mtcnotTargetMod = 0.5; +$mtcturretMod = 0.25; + + +datablock AudioProfile(MTCThinkSound) { + fileName = "fx/misc/bounty_objrem1.wav"; + description = AudioClose3d; + preload = true; + effect = MotionSensorDeployEffect; +}; + +datablock ItemData(mtc) + { + className = Pack; + catagory = "Deployables"; + shapeFile = "ammo_mine.dts"; + mass = 3.0; + elasticity = 0.2; + friction = 0; + rotate = true; + density = 0.1; + heatSignature = 1; + emap = true; + + dynamicType = $TypeMasks::SensorObjectType; + targetNameTag = 'MTC'; + targetTypeTag = 'Unit'; + sensorData = DeployedOutdoorTurretSensor; + }; + + +datablock StaticShapeData(mtcTarget) : StaticShapeDamageProfile + { + className = "target"; + shapeFile = "reticle_bomber.dts"; + }; + + +datablock StaticShapeData(MtcSig) : StaticShapeDamageProfile + { + shapeFile = "Turret_Muzzlepoint.dts"; + className = Target; + dynamicType = $TypeMasks::SensorObjectType; + heatSignature = 1; + targetTypeTag = 'mtc'; + sensorData = DeployedOutdoorTurretSensor; + maxDamage = 1000; + destroyedLevel = 200.20; + disabledLevel = 200.00; + }; + + +datablock ParticleData(mtcJetParticle) +{ + dragCoefficient = 0.0; + gravityCoefficient = 0; + inheritedVelFactor = 0.2; + constantAcceleration = 0.0; + lifetimeMS = 500; + lifetimeVarianceMS = 0; + textureName = "particleTest"; + colors[0] = "0.32 0.47 0.47 1.0"; + colors[1] = "0.32 0.47 0.47 0"; + sizes[0] = 0.40; + sizes[1] = 0.15; +}; + +datablock ParticleEmitterData(mtcJetEmitter) +{ + ejectionPeriodMS = 3; + periodVarianceMS = 0; + ejectionVelocity = 3.0; + velocityVariance = 5.0; + ejectionOffset = 0.0; + overrideAdvances = false; + thetaMin = 110; + thetaMax = 180; + phiReferenceVel = 0; + phiVariance = 360; + + particles = "mtcJetParticle"; +}; + + +datablock TurretData(mtcTurret) : TurretDamageProfile +{ + className = MtcTurret; + shapeFile = "turret_outdoor_deploy.dts"; + + mass = 0.1; + + maxDamage = 2.20; + destroyedLevel = 2.20; + disabledLevel = 2.00; + repairRate = 0; + + deployedObject = true; + + thetaMin = 0; + thetaMax = 145; + thetaNull = 90; + yawVariance = 30.0; // these will smooth out the elf tracking code. + pitchVariance = 30.0; // more or less just tolerances + + + selfpower = true; + maxEnergy = 60; + rechargeRate = 0.256; + + isShielded = false; + energyPerDamagePoint = 360; + + + renderWhenDestroyed = false; + + heatSignature = 0; + + canControl = true; + cmdCategory = "DTactical"; + cmdIcon = CMDTurretIcon; + cmdMiniIconName = "commander/MiniIcons/com_turret_grey"; + firstPersonOnly = true; + + targetTypeTag = 'mtc'; + sensorData = DeployedOutdoorTurretSensor; + sensorRadius = DeployedOutdoorTurretSensor.detectRadius; + sensorColor = "191 0 226"; + + explosion = HandGrenadeExplosion; + expDmgRadius = 5.0; + expDamage = 0.3; + expImpulse = 500.0; + + debrisShapeName = "debris_generic_small.dts"; + debris = TurretDebrisSmall; +}; + +datablock TurretData(LightmtcTurret) : mtcTurret +{ + shapeFile = "turret_outdoor_deploy.dts"; + + mass = 0.1; + + maxDamage = 1.10; + destroyedLevel = 1.10; + disabledLevel = 1.00; + repairRate = 0; + + maxEnergy = 60; + rechargeRate = 0.256; + + isShielded = false; + energyPerDamagePoint = 360; +}; + +datablock TurretData(MediumMtcTurret) : mtcTurret +{ + shapeFile = "turret_outdoor_deploy.dts"; + + mass = 0.1; + + maxDamage = 2.20; + destroyedLevel = 2.20; + disabledLevel = 2.00; + repairRate = 0; + + maxEnergy = 60; + rechargeRate = 0.256; + + isShielded = false; + energyPerDamagePoint = 360; +}; + +datablock TurretData(HeavyMtcTurret) : mtcTurret +{ + shapeFile = "turret_base_large.dts"; + + mass = 0.1; + + maxDamage = 4.40; + destroyedLevel = 4.40; + disabledLevel = 4.40; + repairRate = 0; + + maxEnergy = 60; + rechargeRate = 0.256; + + isShielded = True; + energyPerDamagePoint = 30; + + explosion = TurretExplosion; + expDmgRadius = 15.0; + expDamage = 0.66; + expImpulse = 2000.0; + + debrisShapeName = "debris_generic.dts"; + debris = TurretDebris; +}; + +datablock TurretData(HugeMtcTurret) : mtcTurret +{ + shapeFile = "turret_base_large.dts"; + + mass = 0.1; + + maxDamage = 2.20; + destroyedLevel = 2.20; + disabledLevel = 2.00; + repairRate = 0; + + maxEnergy = 60; + rechargeRate = 0.256; + + isShielded = false; + energyPerDamagePoint = 360; + + explosion = TurretExplosion; + expDmgRadius = 15.0; + expDamage = 0.66; + expImpulse = 2000.0; + + debrisShapeName = "debris_generic.dts"; + debris = TurretDebris; +}; + +function mtcTurret::onDestroyed(%this, %obj, %prevState) + { + if (%obj.isRemoved) + return; + %obj.isRemoved = true; + + %obj.base.Beacon(); + %obj.base.blazetarget(); + %obj.base.specialtarget(); + + Parent::onDestroyed(%this, %obj, %prevState); + + %obj.schedule(500, "delete"); + %obj.base.schedule(500, "delete"); + %killer = %obj.lastDamagedBy; + + %killer.mtckills++; + if (%killer.player.getDatablock().classname $= "armor") + { + if (%killer.player.getMountedImage(0).item $= "SuperChaingun") + { + messageAll('msgSuicide', '\c0%1 pulverized a %2 MTC with an huge amount of super chaingun bullets and got 0.1 points for the effort.',%killer.name,%obj.base.weapon); + %killer.score = %killer.score +0.1; + } + else + { + %score = $mtcScore[%obj.base.weapon] * (1-($mtcnotTargetMod*(%obj.base.target != %killer.player))); + %killer.score = %killer.score +%score; + if (%obj.base.target != %killer.player) + { + messageAll('msgSuicide', '\c0%1 has been awarded %2 points for killing a distracted %3 MTC',%killer.name,%score,%obj.base.weapon); + } + else + { + messageAll('msgSuicide', '\c0%1 has been awarded %2 points for killing a %3 MTC',%killer.name,%score,%obj.base.weapon); + } + messageClient(%killer, 'MsgItemPickup', '\c0You\'ve killed %1 MTC\'s.', %killer.mtckills); + } + if (getRandom()*20+%killer.mtckills>30) + { + echo("bountyhunter"); + spawnMTC("","",10,%killer); + } + } + else if (%killer.getOwner()) + { + %score = $mtcScore[%obj.base.weapon] * (1*$mtcturretMod); + %killer.getOwner().score = %killer.getOwner().score +%score; + %killer.getOwner().mtckills++; + messageClient(%killer, 'MsgItemPickup', '\c0You\'ve killed %1 MTC\'s.', %killer.mtckills); + messageAll('msgSuicide', '\c0%1 \'s turret killed a %3 MTC, and got %2 points for it ',%killer.getOwner().name,%score,%obj.base.weapon); + } + else if (%killer.getClassname() $= "TURRET") + { + if (%killer.IsMtc()) + messageAll('msgSuicide', '\c0A MTC was killed by another MTC',%killer.getOwner().name,%obj.base.weapon); + else + messageAll('msgSuicide', '\c0A MTC was killed by a turret',%killer.getOwner().name,%obj.base.weapon); + } + else + messageAll('msgSuicide', '\c0A MTC was killed',%killer.getOwner().name,%obj.base.weapon); + if (getRandom()*20+%killer.mtckills>30) + { + echo("bountyhunter"); + spawnMTC("","",10,%killer); + } + } + +function mtcTurret::onDamage(%data, %obj) + { + Parent::onDamage(%data, %obj); + %obj.base.aggression = %obj.base.aggression + 0.5; + if (%obj.base.target != %obj.lastDamagedBy && !%obj.base.empsch) + %obj.base.resetorders(); + } + +function MtcTurret::DamageObject(%data,%this, %sourceObject, %position, %amount, %damageType) +{ +if (%sourceObject != %this) + { + if (%sourceObject.client) + %this.lastDamagedBy = %sourceObject.client; + else + %this.lastDamagedBy = %sourceObject; + } + +Parent::DamageObject(%data,%this, %sourceObject, %position, %amount, %damageType); +} + + +function mtcTurret::selectTarget(%this, %turret) +{ + %obj = %turret.base; + + //[[Early abort]] we really can't fire. + if (%obj.nofire) + { + %turret.clearTarget(); + return; + } + + if (%obj.forcetarget()) + { + %turret.setTargetObject(%obj.forcetarget()); + %obj.blazetarget(%obj.forcetarget()); + return ""; + } + + + %TargetSearchMask = $TypeMasks::PlayerObjectType | $TypeMasks::objObjectType | $TypeMasks::StationObjectType | $TypeMasks::GeneratorObjectType | + $TypeMasks::SensorObjectType | $TypeMasks::turretType | $TypeMasks::StaticShapeObjectType | $TypeMasks::ForceFieldObjectType; + + if (!%obj.meddist) + %range = 500; + else + %range = %obj.meddist; + InitContainerRadiusSearch(%turret.getMuzzlePoint(0),%range,%TargetSearchMask); + + + %group = nameToID("MissionCleanup/Deployables"); + + while ((%potentialTarget = ContainerSearchNext()) != 0) + { + if (%potentialtarget) + { //Legal ways + if (%potentialtarget == %turret.base.target || (MTCGroup.blazetarget[%potentialtarget] == 1 && !(%turret.base.weapon $= "target")) ) + { + %fstat =aboveground(%potentialtarget.getworldboxcenter(),1,0); + %stat = GetWord(%fstat,0); + if(%stat $= "open" || %stat $= "roof" || %stat $= "shadow") + { + if (%potentialtarget.isforcefield()) + %turret.setTargetObject(%obj.specialtarget(%potentialtarget,0,1)); + else + %turret.setTargetObject(%potentialtarget); + %obj.blazetarget(%potentialtarget); + return ""; + } + else if (!%potentialtarget.isforcefield()) + { + %top = GetWords(%potentialtarget.seetop(),1,3); + + if (%top !$= "") + { + %turret.setTargetObject(%obj.specialtarget(%potentialtarget,%top,1)); + %obj.blazetarget(%potentialtarget,1); + return ""; + } + } + } + } + } + + %obj.blazetarget(); + %obj.specialtarget(); +} + + +////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////// + + +function startMTC() { + $Host::MTC::Enabled = 1; + autoMTCSpawn(60000,$Host::MTC::MTCMin,$Host::MTC::MTCMax); +} + +function stopMTC() { + $Host::MTC::Enabled = 0; + cancel($MTCSpawn); + MTCGroup.delete(); +} + +function autoMTCSpawn(%time,%min,%max) { + cancel($MTCSpawn); +// %group = nameToID("MissionCleanup/MTCGroup/bases"); + %count = bases.getCount(); + + if (%count < %max) { + for (%c = 0; %c < limit((%min - %count),%min,%max);%c++) { + %weapon = MtcRandomWeapon(); + %pos = pos(RandomPlayer()); + %angle = getRandom() * 2 * $Pi; + %dist = getRandom() * 500 + 500; + %pos = VectorAdd(%pos,getTerrainHeight2( mCos(%angle) * %dist SPC mSin(%angle) * %dist SPC 0)); + spawnMTC(%pos,%weapon); + } + } + $MTCSpawn = schedule(%time,0,"autoMTCSpawn",%time,%min,%max); +} + +function spawnMTC(%pos,%weapon,%aggression,%target) +{ +if ($mtcWeaponSize[%weapon]$="") + %weapon = MtcRandomWeapon(); + + %obj = new Item() { + className = pack; + dataBlock = mtc; + targetNameTag = %weapon; + }; + + %obj.addToMTCGroup(); + %obj.setTransForm(%pos SPC "1 0 0 0"); + %obj.size = $mtcWeaponSize[%weapon]; + + %obj.SetScale($mtcBaseSize[%obj.size]); + if (!%aggression) + %obj.aggression = getRandom()* 5; + else + %obj.aggression = %aggression; + + if (%target) + %obj.forcetarget = %target; + + %obj.nonotify = 1; + + %obj.weapon = %weapon; + + echo(%weapon SPC "mtc spawned with" SPC %obj.aggression SPC "anger level"); + %obj.Initialize(); +} + +function shapebase::addToMTCGroup(%obj,%set) +{ + + if (!isObject(MTCGroup)) + { + %main = new SimGroup("MTCGroup"); + MissionCleanup.add(%TigGroup); + %base = new Simgroup("bases"); + %turrets = new Simgroup("turrets"); + %beacons = new Simgroup("beacons"); + %main.add(%base); + %main.add(%turrets); + %main.add(%beacons); + } +if (%set == 1) + Turrets.add(%obj); +else if (%set == 2) + beacons.add(%obj); +else + bases.add(%obj); + + +} + +function GameBase::isMTC(%obj) { + %name = %obj.getDataBlock().getName(); + if (%name $= "lightMTCTurret") + return 1; + if (%name $= "mediumMTCTurret") + return 1; + if (%name $= "heavyMTCTurret") + return 1; + if (%name $= "HugeMTCTurret") + return 1; + if (%name $= "MTCSig") + return 1; + if (%name $= "MTC") + return 1; + return ""; +} + +function mtc::onCollision(%data,%obj,%col) +{ + +} + +function mtcsig::onCollision(%data,%obj,%col) +{ + +} + + + +function Item::Arm(%obj) +{ +//echo("arm"); +%team = 3; + +//ChainTurret + +%block = "mtcTurret"; +//%turret = TurretData::create(%block); +%size = $mtcWeaponSize[%obj.weapon]; + %turret = new Turret() + { + className = DeployedTurret; + dataBlock = %size @ mtcTurret; + maxdamage = 20; + }; + + +%turret.SetScale($mtcTurretSize[%obj.size]); +%obj.mountObject(%turret, 0); +%obj.mountObject(%sign, 1); + +%turret.setSelfPowered(); +%turret.playThread($DeployThread, "deploy"); +%turret.setRechargeRate(%turret.getDatablock().rechargeRate); + +%barrel = %obj.weapon @ "TurretBarrel"; +%turret.mountImage(%barrel,0,false); + +%obj.turret = %turret; +%turret.base = %obj; + +%turret.team = %team; +setTargetSensorGroup(%turret.getTarget(), %team); + +%turret.addToMTCGroup(1); +} + + + +function getorders() +{ +//%group = nameToID("MissionCleanup/MTCGroup/bases"); +echo(bases.getCount() SPC "mtcs found"); +for( %c = 0; %c < bases.getCount(); %c++ ) + { + %obj = bases.getObject(%c); + if (%obj.order !$= "") + { + %totarg = %totarg+%obj.aggression; + if (mtcCleanTarget(%obj.target)) + { + %target = %obj.target.getDatablock().classname; + if (!%gottar[%target]) + { + %targets++; + %targetname[%targets] = %target; + } + %gottar[%target]++; + + } + %order = %obj.order; + if (!%gotor[%order]) + { + + %orders++; + %odername[%orders] = %order; + } + %gotor[%order]++; + %weapon = %obj.weapon; + if (!%gotweap[%weapon]) + { + + %weapons++; + %weaponname[%weapons] = %weapon; + } + %gotweap[%weapon]++; + } + } +echo(" -" SPC "with an avarage aggression of" SPC %totarg/(bases.getCount()) ); +echo(" +" SPC %orders SPC "order types found"); +for( %c = 1; %c <= %orders; %c++ ) + { + %order = %odername[%c]; + echo(" -" SPC %gotor[%order] SPC "times" SPC %order SPC "ordered"); + } +echo(" +" SPC %targets SPC "target types found"); +for( %c = 1; %c <= %targets; %c++ ) + { + %target = %targetname[%c]; + echo(" -" SPC %gottar[%target] SPC "times" SPC %target SPC "targeted"); + } +echo(" +" SPC %weapons SPC "weapon types found"); +for( %c = 1; %c <= %weapons; %c++ ) + { + %weapon = %weaponname[%c]; + echo(" -" SPC %gotweap[%weapon] SPC "times" SPC %weapon SPC "armed"); + } + +} + +function Item::Notify(%obj,%id) +{ +if (!%obj.nonotify && !$Nomtcnotify) + { + switch$ (%id) { + case "attack": + echo("[[mtc]]" SPC %obj SPC "is attacking" SPC %obj.target.getDatablock().Classname); + echo(" +[[Target]]" SPC %obj.target SPC "is" SPC VectorDist(pos(%obj),pos(%obj.target)) SPC "meters away from mtc"); + case "flee": + echo("[[mtc]]" SPC %obj SPC "is fleeing from" SPC %obj.target.getDatablock().Classname); + echo(" +[[Target]]" SPC %obj.target SPC "is" SPC VectorDist(pos(%obj),pos(%obj.target)) SPC "meters away from mtc"); + case "roam": + echo("[[mtc]]" SPC %obj SPC "is roaming around" SPC %obj.target.getDatablock().Classname); + echo(" +Closest [[target]]" SPC %obj.target SPC "is" SPC VectorDist(pos(%obj),pos(%obj.target)) SPC "meters away from mtc"); + case "repair": + echo("[[mtc]]" SPC %obj SPC "is repairing at" SPC MFloor(%obj.turret.getDamagePct() *100) @"% damage and" SPC MFloor(%obj.ammo["flare"]) SPC "flares"); + case "ammo": + echo("[[mtc]]" SPC %obj SPC "has:"); + echo(" + " @ MFloor(%obj.ammo["flare"]) SPC "flares"); + echo(" + " @ MFloor(%obj.ammo["mine"]) SPC "mines"); + echo(" + " @ MFloor(%obj.ammo["cloak"]) SPC "cloak seconds"); + echo(" and an aggression level of" SPC MFloor(%obj.aggression)); + } + } +} + +function mtcnerfwar() +{ +for( %c = 0; %c < ClientGroup.getCount(); %c++ ) + { + %client = ClientGroup.getObject(%c); + spawnMTC("0 0 0","nerf",10,%client); + } +} + + +function Item::blazetarget(%obj,%target,%set) +{ +//echo("blazetarget"); +%obj.cloak(); +if (%obj.weapon $= "target") + { + if (%set) + { + if (%obj.blazetarget == %target) + return ""; + else if (IsObject(%target)) + { + %obj.blazetarget(); + %obj.blazetarget = %target; + MTCGroup.blazetarget[%target] = 1; + } + } + else + { + MTCGroup.blazetarget[%obj.blazetarget] = 0; + %obj.blazetarget = ""; + } + } +} + + +function Item::VisTarget(%obj,%linkobj,%pos,%dir,%sided) +{ +//echo("visTarget"); +if (!Isobject(%obj.vistarget1)) + { + %tar1 = new StaticShape() + { + className = Target; + dataBlock = mtcTarget; + scale = "0.25 0.25 0.25"; + }; + } +else + %tar1 = %obj.vistarget1; + +if (%pos $= "" && Isobject(%linkobj)) + %pos = pos(%linkobj); +else if (%pos $= "") + %pos = pos(%obj); + +%rot1 = fullrot(%dir,"0 0 1"); +%tar1.setTransform(%pos SPC %rot1); +%obj.vistarget1 =%tar1; +%tar1.schedule(60000,"delete"); + + if (%sided) + { + if (!Isobject(%obj.vistarget2)) + { + %tar2 = new StaticShape() + { + className = Target; + dataBlock = mtcTarget; + scale = "0.25 0.25 0.25"; + }; + } + else + %tar2 = %obj.vistarget2; + + %rot2 = fullrot(VectorScale(%dir,-1),"0 0 1"); + %tar2.setTransform(%pos SPC %rot2); + %obj.vistarget2 = %tar2; + %tar2.schedule(60000,"delete"); + } + +return %tar1; +} + +function Item::specialtarget(%obj,%target,%pos,%set) +{ +//echo("specialtarget"); +if (%set) + { + if (%pos !$= "") + { + %ppos = getTerrainHeight2(%target.getWorldboxCenter()); + %res = containerRayCast(%obj.turret.getWorldboxCenter(),VectorAdd(%ppos,"0 0 0.1"), -1,%obj.turret); + if (GetWord(%res,0) == %target) + { + %dir = realvec(%target,NormalFromRaycast(%res)); + %pos = VectorAdd(PosFromRaycast(%res),VectorScale(%dir,0.1)); + } + else + { + %dir = "0 0 1"; + } + } + else + { + %pos = %target.getWorldboxCenter(); + %dir = VectorNormalize(VectorSub(%pos,pos(%obj.turret))); + %rot1 = fullrot(%dir,0); + %rot2 = fullrot(VectorScale(%dir,-1)); + } + + return %obj.VisTarget(%target,%pos,%dir,1); + } +else + { + if (isObject(%obj.vistarget1)) + %obj.vistarget1.delete(); + if (isObject(%obj.vistarget2)) + %obj.vistarget2.delete(); + } +} + +function Item::canfire(%obj,%set) +{ +//echo("canfire"); +if (%set $= "target") + { + %obj.canfire = "target"; + %obj.nofire = ""; + if (%obj.turret.getTargetObject() && %obj.turret.getTargetObject() != %obj.target) + %obj.turret.clearTarget(); + } +else if (%set $= "all") + { + %obj.canfire = "all"; + %obj.nofire = ""; + } +else if (!%set) + { + %obj.turret.clearTarget(); + %obj.nofire = 1; + %obj.canfire = "none"; + } +} + + +////////////////////////////////////////////// +//////////////Inventory Actions/////////////// +////////////////////////////////////////////// + +//Telleportation + +function Item::telleport(%obj,%loc) +{ +//echo("telleport"); +if (!%obj.notelle) + { + if (!%obj.notellefx) + { + teleportStartFX(%obj); + teleportStartFX(%obj.turret); + %obj.schedule(1002,"teleportEndFX",%obj); + %obj.turret.schedule(1002,"teleportEndFX",%obj.turret); + %obj.play3D(TelePadBeamSound); + } + %obj.schedule(1001,"SetTransform",%loc SPC rot(%obj)); + %obj.turret.schedule(1001,"SetTransform",%loc SPC rot(%obj.turret)); + } +} + +//cloaking + +function Item::cloak(%obj,%set) +{ +//echo("cloak"); +// We need atleast 20 seconds to activate cloak +if (%set && %obj.ammo["cloak"] >= 20 && !%obj.cloaked && !%obj.nocloak && getSimTime()-%obj.lastcloaktime>5000) + { + %obj.cloaked = 1; + %obj.setCloaked(True); + %obj.turret.setCloaked(True); + %obj.cloaktime = getsimtime(); + %obj.silent(1); + %obj.schedule(%obj.ammo["cloak"]*1000,"cloak",0); + %obj.lastcloaktime = GetSimTime(); + } +else if (!%set) + { + if (%obj.cloaked) + { + %obj.ammo["cloak"]= %obj.ammo["cloak"]-(getSimtime()-%obj.cloaktime)/1000; + %obj.cloaked = 0; + } + if (%obj.silent) + %obj.silent(); + if (%obj.isCloaked()) + %obj.setCloaked(False); + if (%obj.turret.isCloaked()) + %obj.turret.setCloaked(False); + %obj.beacon(1); + } +} + +function Item::silent(%obj,%set) +{ +//echo("silent"); +if (!%obj.nosilent && %set) + { + if (!%obj.attackcloak) + { + %obj.canfire(); + %obj.flash(); + } + //%obj.turret.setHeat(0); + %obj.noflare = 1; + %obj.notellefx = 1; + %obj.nojet = 1; + %obj.nosound = 1; + %obj.nobeacon = 1; + %obj.Beacon(); + %obj.silent = 1; + } +else if (!%set) + { + //%obj.turret.setHeat(1); + %obj.canfire("target"); + %obj.notellefx = ""; + %obj.noflare = ""; + %obj.nojet = ""; + %obj.nosound = ""; + %obj.nobeacon = ""; + %obj.noflare = ""; + %obj.silent = ""; + } +} + + +//Mines + +function Item::Mine(%obj) + { +//echo("mine"); + if (%obj.ammo["mine"] > 0 && !%obj.nomine && %obj.lastThrowtime + 5000 < getSimTime()) + { + %obj.ammo["mine"] = %obj.ammo["mine"] -1; + + %thrownItem = new Item() + { + dataBlock = MineDeployed; + sourceObject = %obj; + }; + + MissionCleanup.add(%thrownItem); + + // throw it + %dir = VectorNormalize(VectorSub(%obj.target.getWorldboxCenter(),%obj.getWorldboxCenter())); + %vec = vectorScale(%dir, (20.0)); + + // add a vertical component to give it a better arc + %dot = vectorDot("0 0 1", %dir); + if(%dot < 0) + %dot = -%dot; + %vec = vectorAdd(%vec, vectorScale("0 0 4", 1 - %dot)); + + // add player's velocity + %vec = vectorAdd(%vec, vectorScale(%obj.getVelocity(), 0.4)); + %pos = %obj.getWorldboxCenter(); + + %thrownItem.sourceObject = %obj; + %thrownItem.team = %obj.team; + %thrownItem.setTransform(%pos); + + %thrownItem.applyImpulse(%pos, %vec); + %thrownItem.setCollisionTimeout(%obj); + serverPlay3D(GrenadeThrowSound, %pos); + %obj.lastThrowtime = getSimTime(); + + %thrownItem.getDataBlock().onThrow(%thrownItem, %obj); + schedule(30 * 60 * 1000,0,"explodeMine",%thrownItem, true); + } + + } + +// Flares + +function Item::flare(%obj) +{ +//echo("flare"); +if (%obj.ammo["flare"] > 0 && !%obj.noflare) + { + %obj.ammo["flare"] = %obj.ammo["flare"] - 1; + %size = getRandom() * 3; + %p = new FlareProjectile() { + dataBlock = FlareGrenadeProj; + initialDirection = "0 0" SPC %size; + initialPosition = %obj.getWorldboxCenter(); + sourceObject = %obj; + sourceSlot = 0; + }; + FlareSet.add(%p); + MissionCleanup.add(%p); + serverPlay3D(GrenadeThrowSound, %obj.getWorldboxCenter()); + %p.schedule(6000, "delete"); + } +} + +function Item::Incomming(%obj) +{ +InitContainerRadiusSearch(%obj.getWorldboxCenter(),500,-1); +while ((%target = ContainerSearchNext()) != 0) + { + if (MissileSet.isMember(%target)) + { + if (%target.gettargetobject() == %obj) + { + return %target; + } + } + } +return ""; +} + + + +//Flash + +function Item::Flash(%obj) +{ +//echo("flash"); +if (%obj.ammo["flash"] > 0 && !%obj.noflash) + { + %obj.ammo["flash"] = %obj.ammo["flash"] - 1; + %size = getRandom() * 3; + + %flash = new Item() + { + dataBlock = FlashGrenadeThrown; + sourceObject = %obj; + }; + %flash.setTransform(VectorAdd(pos(%obj),"0 0 4") SPC "1 0 0 0"); + + schedule(500,0,"detonateFlashGrenade",%flash); + MissionCleanup.add(%flash); + serverPlay3D(GrenadeThrowSound, %obj.getWorldboxCenter()); + } +} + + +//Jetting + +function ShapeBase::Jet(%obj,%time) +{ + +if (isObject(%obj) && !%obj.nojet && !$nojet) + { + if ($MTC::FancyJet) + { + for (%c = 0; %c < (%time/50); %c++) + { + %obj.schedule(%c*50,"JetPoof",50); + } + } + else + { + createLifeEmitter(%obj.getworldBoxCenter(), mtcJetEmitter, 100); + } + } +} +//SmallLightDamageSmoke +function Shapebase::JetPoof(%obj,%time) +{ +if (isObject(%obj) && !%obj.nojet) + { + %pos = %obj.getWorldboxCenter(); + %obj.firePoof = new ParticleEmissionDummy() + { + position = %pos; + rotation = ""; + DataBlock = "defaultEmissionDummy"; + lockCount = "0"; + homingCount = "0"; + emitter = "mtcJetEmitter"; + velocity = "10"; + }; + MissionCleanup.add(%obj.firePoof); + %obj.firePoof.schedule(%time, "delete"); + + + } +} + +/// + +function GiveSign(%obj) +{ +if (!IsObject(%obj.signature)) + { + %sign = new StaticShape(){ + dataBlock = MtcSig; + }; + } + else + %sign = %obj.signature; + + %sign.setTransform(%obj.getTransform()); + %sign.team = %obj.team; + %sign.setHeat(1); + %obj.mountObject(%sign, 4); + setTargetSensorGroup(%sign.getTarget(), %obj.team); + + %obj.signature = %sign; + %sign.owner = %obj; + CheckSign(%sign); + return %sign; +} + +function CheckSign(%sign) +{ +if (!IsObject(%sign.owner)&& IsObject(%sign)) + { + %sign.delete(); + } +else if (IsObject(%sign.owner)&& IsObject(%sign)) + Schedule(30000,0,"CheckSign",%sign); +} + +function Item::beacon(%obj,%set) +{ + + +if (%set && !%obj.nobeacon && !%obj.turret.isRemoved && IsObject(%obj)) + { + + if (!IsObject(%obj.enemyBeacon1)) + { + %beacon1 = new BeaconObject(){ + datablock = BomberBeacon; + }; + + } + else + %beacon1 = %obj.enemyBeacon1; + if (!IsObject(%obj.enemyBeacon2)) + { + %beacon2 = new BeaconObject(){ + datablock = BomberBeacon; + }; + } + else + %beacon2 = %obj.enemyBeacon2; + + + + %beacon1.team = 2; + %beacon2.team = 1; + %beacon1.owner = %obj; + %beacon2.owner = %obj; + + %beacon1.setTarget(2); + %beacon2.setTarget(1); + %obj.mountObject(%beacon1, 4); + %obj.mountObject(%beacon2, 5); + %obj.enemyBeacon1 = %beacon1; + %obj.enemyBeacon2 = %beacon2; + %beacon1.addToMTCGroup(2); + %beacon2.addToMTCGroup(2); + %beacon1.setBeaconType(friend); + %beacon2.setBeaconType(friend); + %sign = GiveSign(%obj.turret); + %sign.addToMTCGroup(2); + //%obj.turret.mountObject(%sign,4); + } +else + { + if (IsObject(%obj.enemyBeacon1)) + { + %obj.enemyBeacon1.delete(); + %obj.enemyBeacon1 = ""; + } + if (IsObject(%obj.enemyBeacon2)) + { + %obj.enemyBeacon2.delete(); + %obj.enemyBeacon2 = ""; + } + if (IsObject(%obj.turret.signature)) + { + %obj.turret.signature.delete(); + %obj.turret.signature = ""; + } + } +} + +function Item::Sound(%obj,%id) +{ + +if (!%obj.nosound) + { + switch$ (%id) { + case "think": + %obj.play3D(MTCThinkSound); + case "move": + %obj.play3D(SkiAllSoftSound); + } + } +} + +function Item::Emp(%obj,%time) +{ +//echo("emp"); +cancel(%obj.empsch); +cancel(%obj.invloop); +cancel(%obj.evalloop); +cancel(%obj.mainrun); +%obj.canfire = ""; +%obj.nofire = 1; +%obj.turret.clearTarget(); +//%obj.zaplight(%time); +//createLifeEmitter(%obj.getWorldboxCenter(),ELFSparksEmitter, limit(%time-500,0)); +%obj.turret.zapobject(); +%obj.empsch = %obj.schedule(%time,"unEmp"); +} + +function Item::unEmp(%obj) +{ +echo("umemp"); +cancel(%obj.empsch); +%obj.empsch = ""; +%obj.turret.stopzap(); +%obj.nofire = ""; +%obj.invloop(); +%obj.evaluate(); +} + + +//////////////////////////////////////////////////////////// +///////////////////SHIELDING SYSTEM///////////////////////// +//////////////////////////////////////////////////////////// + + +function gameConnection::antiMissile(%obj) +{ +cancel(%obj.shieldsch); +if (!IsObject(%obj)) +return ""; +if (IsObject(%obj.player)) + %obj.player.pointdeflaser(); +%obj.shieldsch = %obj.schedule(500,"antiMissile"); +} + +function ShapeBase::GetHoming(%obj) +{ + +if (!%obj.homingcount) + return ""; +InitContainerRadiusSearch(%obj.getWorldBoxCenter(),75,-1); +while ((%target = ContainerSearchNext()) != 0) + { + if (MissileSet.isMember(%target)) + { + if (%target.getTargetObject() == %obj) + { + return %target; + } + } + } +return ""; +} + + +function MissileBarrelLarge::onFire(%data,%obj,%slot) +{ + %p = Parent::onFire(%data,%obj,%slot); + Missileset.add(%p); + if (%obj.getControllingClient()) + { + // a player is controlling the turret + %target = %obj.getLockedTarget(); + } + else + { + // The ai is controlling the turret + %target = %obj.getTargetObject(); + } + + if(%target) + %p.setObjectTarget(%target); + else if(%obj.isLocked()) + %p.setPositionTarget(%obj.getLockedPosition()); + else + %p.setNoTarget(); // set as unguided. Only happens when itchy trigger can't wait for lock tone. +} + + +function ShapeBase::PointDefLaser(%obj) +{ + +if (%missile = %obj.getHoming()) + { + %pos = %obj.getWorldboxCenter(); + %result = Zaplos(%pos,%missile,0,%obj.owner); + if (GetWord(%result,0)) + { + %lastpos = %missile.getWorldboxCenter(); + schedule(100,0,"putscreen",%obj,%missile,%lastpos); + } + } +} + +function putscreen(%obj,%missile,%lastpos) +{ +%newpos = %missile.getWorldboxCenter(); +%step = VectorSub(%lastpos,%newpos); +%pos = %obj.getWorldBoxCenter(); +%obj.screen(VectorAdd(%pos,%step),VectorNormalize(%step)); +} + +function ShapeBase::ActiveShield(%obj) +{ +cancel(%obj.shieldsch); +InitContainerRadiusSearch(%obj.getWorldBoxCenter(),50,-1); +echo("shield"); +while ((%target = ContainerSearchNext()) != 0) + { + if (%obj.IsEnemy(%target.sourceobject)) + { + %pos = %target.getWorldBoxCenter(); + %dir = VectorNormalize(VectorSub(%obj.getWorldBoxCenter(),%pos)); + %obj.schedule(10+%count*10,"screen",VectorAdd(%pos,%dir),%dir); + %count++; + } + } +%obj.shieldsch = %obj.schedule(100,"activeShield"); +} + +function ShieldTrack(%obj,%target,%lastpos) +{ +if (!isObject(%obj) || !IsObject(%target)) + return ""; +%pos = %obj.getWorldBoxCenter(); +%newpos = %target.getWorldBoxCenter(); +%lastdist = VectorDist(%pos,%lastpos); +%newdist = VectorDist(%pos,%newpos); + +if (%lastdist < %newdist) + return ""; + +if (%newdist < 30) + %obj.screen(%spos,%dir); +} + +function ShapeBase::screen(%owner,%pos,%nrm) +{ +cancel(%screen.del); +if (!ISObject(%owner.screen)) + { + %screen = new ForceFieldBare() + { + DataBlock = DeployedForceField3; + scale = "5 5 0.1"; + }; + } + else + %screen = %owner.screen; + %left= VectorCross(%nrm,"0 0 1"); + %up = VectorCross(%left,%nrm); + %offset = VectorScale(VectorAdd(%left,%up),-2.5); + %rot = Fullrot(%nrm,"0 0 1"); + %screen.setTransform(VectorAdd(%pos,%offset) SPC %rot); + %owner.screen = %screen; + %screen.del = %screen.Schedule(500,"delete"); + +} + +function LockedMissile(%pos,%dir,%obj) +{ +%p = new SeekerProjectile() { + dataBlock = ShoulderMissile; + initialDirection = %dir; + initialPosition = %pos; + //sourceObject = ""; + //sourceSlot = %obj.fireslot; + //vehicleObject = %obj; + }; + //%p = Parent::onFire(%data, %obj, %slot); + MissileSet.add(%p); + %p.setObjectTarget(%obj); + +} + + +///////////////////////////////////////////////////////////// +///////////////////////Camp////////////////////////////////// +///////////////////////////////////////////////////////////// + +function Shapebase::startterrainscan(%obj,%type) +{ +if (%type == 1) + { + %obj.terrainscan(2,0,180,1,0,20,50); + %obj.terrainscan(2,0,-180,-1,0,20,50); + %obj.maxresult = 2; + } +else if (%type == 2) + { + %obj.terrainscan(2,0,180,1,0,20,2000); + %obj.terrainscan(2,0,-180,-1,0,20,2000); + %obj.terrainscan(2,0,180,1,10,20,2000); + %obj.terrainscan(2,0,-180,-1,10,20,2000); + %obj.terrainscan(2,0,180,1,20,20,2000); + %obj.terrainscan(2,0,-180,-1,20,20,2000); + %obj.maxresult = 6; + } +else + %obj.terrainscan(2,0,360,1,0,20,50); +} + +function Shapebase::terrainscan(%obj,%height,%startangle,%maxangle,%tick,%pitch,%minrange,%maxrange) +{ +%pos = %obj.getWorldboxCenter(); +%rot = %obj.getRotation(); +%targeter = new StaticShape() + { + position = %pos; + rotation = %rot; + datablock = "LightningTarget"; + }; +%targeter.center = %obj; +%targeter.initialrot = GetWord(%rot,3)+mDegtoRad(%startangle); + +%targeter.height = %height; +%targeter.maxangle = %maxangle; +%targeter.tick = %tick; +%targeter.pitch = mDegtoRad(%pitch); +%targeter.minrange = %minrange; +%targeter.maxrange = %maxrange; + +%pointer = new TargetProjectile() + { + dataBlock = BasicTargeter; + initialDirection = "0 0 1"; + initialPosition = "0 0 1"; + sourceObject = %targeter; + damageFactor = 1; + sourceSlot = 0; + }; +%targeter.pointer = %pointer; +%targeter.scandir(%tick); +} + + + + +function Shapebase::ScanDir(%obj,%dir) +{ +//Aim beam +%rot = mDegToRad(%dir)+%obj.initialrot; +%rotation = rotadd("0 0 1" SPC %rot,"1 0 0" SPC %obj.pitch); +%vec = mSin(%rot)*mCos(%obj.pitch) SPC mCos(%rot)*mCos(%obj.pitch) SPC -1*mSin(%obj.pitch); +%offset = VectorAdd("0 0" SPC %obj.height,%vec); + +%pos = VectorAdd(getTerrainHeight2(%obj.center.getWorldboxCenter()),%offset); +%obj.setTransform(%pos SPC %rotation); + +///Cast terrain +%mask = $TypeMasks::TerrainObjectType | $TypeMasks::InteriorObjectType; +%res = ContainerRayCast(%pos,VectorAdd(%pos,VectorScale(%vec,%obj.maxrange)),%mask, %obj.center); + +if ((!%res && %obj.maxrange) || VectorDist(%pos,GetWords(%res,1,3)) < %obj.minrange) + %obj.result++; + +if (mAbs(%dir) >= mAbs(%obj.maxangle)) + %obj.terrainscanned(); +else + %obj.schedule(10,"Scandir",%dir+%obj.tick); +} + +function Shapebase::terrainscanned(%obj) +{ +%obj.center.result = stripEndSpaces(%obj.center.result SPC %obj.result); +%result = %obj.center.result; +if (getWordCount(%result) >= limit(%obj.center.maxresult,1)) + { + echo(%result); + %obj.center.result = ""; + } +%obj.pointer.delete(); +%obj.delete(); +} + diff --git a/scripts/MTC_eWeap.cs b/scripts/MTC_eWeap.cs new file mode 100644 index 0000000..50fcc6f --- /dev/null +++ b/scripts/MTC_eWeap.cs @@ -0,0 +1,531 @@ +///Using new weapon mode switching logic :D :D + +$WeaponSettings1[TractorGunImage] = "7 -1 TractorGun:[Power]"; +$WeaponSetting1[TractorGunImage,0] = "Grapling Power 1"; +$WeaponSetting1[TractorGunImage,1] = "Grapling Power 2"; +$WeaponSetting1[TractorGunImage,2] = "Grapling Power 3"; +$WeaponSetting1[TractorGunImage,3] = "Grapling Power 4"; +$WeaponSetting1[TractorGunImage,4] = "Grapling Power 5"; +$WeaponSetting1[TractorGunImage,5] = "Grapling Power 10"; +$WeaponSetting1[TractorGunImage,6] = "Grapling Power 125"; +$WeaponSetting1[TractorGunImage,7] = "Grapling Power 256"; + + +$WeaponSettings2[TractorGunImage] = "5 -1 TractorGun:[Direction]"; +$WeaponSetting2[TractorGunImage,0] = "Pull target"; +$WeaponSetting2[TractorGunImage,1] = "Push target"; +$WeaponSetting2[TractorGunImage,2] = "Keep target at 10 meters distance"; +$WeaponSetting2[TractorGunImage,3] = "Pull user"; +$WeaponSetting2[TractorGunImage,4] = "Push user"; +$WeaponSetting2[TractorGunImage,5] = "Keep user at 10 meters distance"; + + +datablock ItemData(TractorGun) +{ + className = Weapon; + catagory = "Spawn Items"; + shapeFile = "weapon_elf.dts"; + image = TractorGunImage; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 2; + pickUpName = "an Tractor gun"; + + computeCRC = true; + emap = true; +}; + + + +/////////////////////////////////////////////////// +////////////////Tractor Beam/////////////////////// +/////////////////////////////////////////////////// + +datablock ELFProjectileData(TractorBeam) +{ + beamRange = 150; + numControlPoints = 8; + restorativeFactor = 3.75; + dragFactor = 4.5; + endFactor = 2.25; + randForceFactor = 2; + randForceTime = 0.125; + drainEnergy = 0.0; + drainHealth = 0.0; + directDamageType = $DamageType::ELF; + mainBeamWidth = 0.1; // width of blue wave beam + mainBeamSpeed = 9.0; // speed that the beam travels forward + mainBeamRepeat = 0.25; // number of times the texture repeats + lightningWidth = 0.5; + lightningDist = 0.5; // distance of lightning from main beam + + fireSound = ElfGunFireSound; + wetFireSound = ElfFireWetSound; + + textures[0] = "special/Sniper"; + textures[1] = "special/FlareSpark"; + textures[2] = "special/Redflare"; + + emitter = FlareEmitter; +}; + + +datablock ShapeBaseImageData(TractorGunImage) +{ + className = WeaponImage; + + shapeFile = "weapon_elf.dts"; + item = TractorGun; + offset = "0 0 0"; + + projectile = TractorBeam; + projectileType = ELFProjectile; + deleteLastProjectile = true; + emap = true; + + + usesEnergy = true; + minEnergy = 3; + + stateName[0] = "Activate"; + stateSequence[0] = "Activate"; + stateSound[0] = ELFGunSwitchSound; + stateTimeoutValue[0] = 0.5; + stateTransitionOnTimeout[0] = "ActivateReady"; + + stateName[1] = "ActivateReady"; + stateTransitionOnAmmo[1] = "Ready"; + stateTransitionOnNoAmmo[1] = "NoAmmo"; + + stateName[2] = "Ready"; + stateTransitionOnNoAmmo[2] = "NoAmmo"; + stateTransitionOnTriggerDown[2] = "CheckWet"; + + stateName[3] = "Fire"; + stateEnergyDrain[3] = 5; + stateFire[3] = true; + stateAllowImageChange[3] = false; + stateScript[3] = "onFire"; + stateTransitionOnTriggerUp[3] = "Deconstruction"; + stateTransitionOnNoAmmo[3] = "Deconstruction"; + //stateSound[3] = ElfFireWetSound; + + stateName[4] = "NoAmmo"; + stateTransitionOnAmmo[4] = "Ready"; + + stateName[5] = "Deconstruction"; + stateScript[5] = "deconstruct"; + stateTransitionOnTimeout[5] = "Ready"; + stateTransitionOnNoAmmo[6] = "NoAmmo"; + + stateName[6] = "DryFire"; + stateSound[6] = ElfFireWetSound; + stateTimeoutValue[6] = 0.5; + stateTransitionOnTimeout[6] = "Ready"; + + stateName[7] = "CheckWet"; + stateTransitionOnWet[7] = "DryFire"; + stateTransitionOnNotWet[7] = "Fire"; +}; + +datablock TurretImageData(TractorTurretBarrel) +{ + + + shapeFile = "turret_Elf_large.dts";//"weapon_elf.dts";// + item = ELFGun; + + projectile = TractorBeam; + projectileType = ELFProjectile; + + deleteLastProjectile = true; + emap = true; + + + UsesEnergy = true; + minEnergy = 0.1; + fireEnergy = 0.1; + + rotation = "0 1 0 90"; + offset = "0 -0.5 0"; + + yawVariance = 30.0; // these will smooth out the elf tracking code. + pitchVariance = 30.0; // more or less just tolerances + // Turret parameters + activationMS = 500; + deactivateDelayMS = 100; + thinkTimeMS = 100; + degPerSecTheta = 580; + degPerSecPhi = 960; + attackRadius = 500; + + + yawVariance = 60.0; // these will smooth out the elf tracking code. + pitchVariance = 60.0; // more or less just tolerances + + + // State transiltions + stateName[0] = "Activate"; + stateTransitionOnNotLoaded[0] = "Dead"; + stateTransitionOnLoaded[0] = "ActivateReady"; + + stateName[1] = "ActivateReady"; + stateSequence[1] = "Activate"; + stateSound[1] = EBLSwitchSound; + stateTimeoutValue[1] = 1; + stateTransitionOnTimeout[1] = "Ready"; + stateTransitionOnNotLoaded[1] = "Deactivate"; + stateTransitionOnNoAmmo[1] = "NoAmmo"; + + stateName[2] = "Ready"; + stateTransitionOnNotLoaded[2] = "Deactivate"; + stateTransitionOnTriggerDown[2] = "Fire"; + stateTransitionOnNoAmmo[2] = "NoAmmo"; + + stateName[3] = "Fire"; + stateFire[3] = true; + stateRecoil[3] = LightRecoil; + stateAllowImageChange[3] = false; + stateSequence[3] = "Fire"; + stateSound[3] = EBLFireSound; + stateScript[3] = "onFire"; + stateTransitionOnTriggerUp[3] = "Deconstruction"; + stateTransitionOnNoAmmo[3] = "Deconstruction"; + + stateName[4] = "Reload"; + stateTimeoutValue[4] = 0.01; + stateAllowImageChange[4] = false; + stateSequence[4] = "Reload"; + stateTransitionOnTimeout[4] = "Ready"; + stateTransitionOnNotLoaded[4] = "Deactivate"; + stateTransitionOnNoAmmo[4] = "NoAmmo"; + + stateName[5] = "Deactivate"; + stateSequence[5] = "Activate"; + stateDirection[5] = false; + stateTimeoutValue[5] = 1; + stateTransitionOnLoaded[5] = "ActivateReady"; + stateTransitionOnTimeout[5] = "Dead"; + + stateName[6] = "Dead"; + stateTransitionOnLoaded[6] = "ActivateReady"; + + stateName[7] = "NoAmmo"; + stateTransitionOnAmmo[7] = "Reload"; + stateSequence[7] = "NoAmmo"; + + stateName[8] = "Deconstruction"; + stateScript[8] = "deconstruct"; + stateTransitionOnNoAmmo[8] = "NoAmmo"; + stateTransitionOnTimeout[8] = "Reload"; + stateTimeoutValue[8] = 0.1; +}; + +function TractorBeam::zapTarget(%data, %projectile, %target, %targeter) +{ +%projectile.checkTractorStatus(%data, %target, %targeter); +} + +function TractorTurretBarrel::onFire(%data, %obj, %slot) +{ +//if (getSimTime()-%target.swingend > 5000) + %p = Parent::onFire(%data, %obj, %slot); +} + +function ELFProjectile::checkTractorStatus(%this, %data, %target, %targeter) +{ + %obj = %this.sourceObject; + if((isObject(%target)) && (isObject(%obj))) + { + if(%target.getDamageState() $= "Destroyed") + { + cancel(%this.Tractorrecur); + %this.delete(); + %targeter.base.resetorders(); + return; + } + + %data = %target.getDataBlock(); + %data2 = %targeter.getDataBlock(); + %pos = %target.getWorldBoxCenter(); + %pos2 = %targeter.getWorldBoxCenter(); + if (%targeter.IsMtc()) + %pos2= VectorAdd(%pos2,"0 0 15"); + %vec = VectorSub(%pos2,%pos); + %dist = VectorLen(%vec); + %dir = VectorNormalize(%vec); + %set = %targeter.weaponSet1; + if (%set !$="") + %speed = getWord($WeaponSetting1[TractorGunImage,%targeter.weaponSet1],2); + else + %speed = 5; + + %dspeed = Limit((%dist-10)/10,-1,1); + if (%targeter.weaponSet2 == 2 || %targeter.weaponSet2 == 5) + { + %speed = %dspeed*%dspeed*%speed; + %dir = VectorScale(%dir,Lev(%dspeed)); + } + + if (%targeter.weaponSet2 == 1 || %targeter.weaponSet2 == 4) + %dir = VectorScale(%dir,-1); + //%amount = VectorScale(%dir, Limit((10000/%dist),0,10000)); + if (%client = %targeter.client) + %admin = (%client.isAdmin || %client.isSuperAdmin); + + %wantuser = (%targeter.weaponSet2 > 2); + %tisplayer = (%target.getType() & $TypeMasks::PlayerObjectType); + %tisgveh = (%target.getType() & $TypeMasks::VehicleObjectType && !%obj.disableMove); + %allowed = ((%target.team != %obj.team) || ($teamDamage || %admin)); + + if (%allowed && (%tisplayer || %tisgveh) && !%wantuser) + { + if(%obj.getObjectMount() != %target && %this.hasTarget()) + { + %limit = (%target.getType() & $TypeMasks::VehicleObjectType); + %size = Limit(3*%data.mass*%speed,0,10000*(1+9*%limit)); + %amount = VectorScale(%dir, %size); + %target.applyImpulse(%pos, %amount); + } + } + else + { + if(%obj.getObjectMount() != %target && %this.hasTarget()) + { + %size = Limit(3*%data2.mass*%speed,0,10000); + %amount = VectorScale(%dir, %size); + %targeter.applyImpulse(%pos2, VectorScale(%amount,-1)); + } + } + %this.TractorRecur = %this.schedule(70, checkTractorStatus, %data, %target, %targeter); + } +} + +///////////////////////////////////////////////////////////////////////////////// +/////////////////////////////SwarmDisc//////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////// + + +datablock SeekerProjectileData(SeekingDisc) +{ + projectileShapeName = "disc.dts"; + emitterDelay = -1; + directDamage = 0.0; + hasDamageRadius = true; + indirectDamage = 0.10; + damageRadius = 7.5; + radiusDamageType = $DamageType::Disc; + kickBackStrength = 1750; + + sound = discProjectileSound; + explosion = "DiscExplosion"; + underwaterExplosion = "UnderwaterDiscExplosion"; + splash = DiscSplash; + + + velInheritFactor = 0.5; + fizzleTimeMS = 50000; + lifetimeMS = 50000; + explodeOnDeath = true; + reflectOnWaterImpactAngle = 15.0; + explodeOnWaterImpact = true; + deflectionOnWaterImpact = 0.0; + fizzleUnderwaterMS = 5000; + + + baseEmitter = HumanArmorJetEmitter; + delayEmitter = HumanArmorJetEmitter; + + exhaustEmitter = DiscMistEmitter; + exhaustTimeMs = 300; + exhaustNodeName = "muzzlePoint1"; + + + muzzleVelocity = 10.0; + maxVelocity = 30.0; + turningSpeed = 110.0; + acceleration = 5; + + proximityRadius = 0; + + terrainAvoidanceSpeed = 180; + terrainScanAhead = 25; + terrainHeightFail = 12; + terrainAvoidanceRadius = 100; + + + activateDelayMS = 200; + + hasLight = true; + lightRadius = 6.0; + lightColor = "0.175 0.175 0.5"; + +}; + + +datablock TurretImageData(SwarmDiscTurretBarrel) +{ + + shapeFile = "turret_AA_large.dts";//weapon_missile.dts"; + item = MissileLauncher; + //ammo = MissileLauncherAmmo; + armThread = lookms; + emap = true; + + projectile= SeekingDisc; + projectileType= SeekerProjectile; + + isSeeker = true; + seekRadius = 900; + maxSeekAngle = 90; + seekTime = 5.0; + minSeekHeat = 0.0; // the heat that must be present on a target to lock it. + yawVariance = 30.0; // these will smooth out the elf tracking code. + pitchVariance = 30.0; // more or less just tolerances + + usesEnergy = true; + fireEnergy = 5; + minEnergy = 5; + projectileSpread = 0.01; + + + offset = "0.7 -0.04 -0.45"; + rotation = "0 1 0 -90"; + + // only target objects outside this range + minTargetingDistance = 4; + + // Turret parameters + activationMS = 250; + deactivateDelayMS = 500; + thinkTimeMS = 200; + degPerSecTheta = 580; + degPerSecPhi = 1080; + attackRadius = 500; + + // State transitions + stateName[0] = "Activate"; + stateTransitionOnNotLoaded[0] = "Dead"; + stateTransitionOnLoaded[0] = "ActivateReady"; + + stateName[1] = "ActivateReady"; + stateSequence[1] = "Activate"; + stateSound[1] = MBLSwitchSound; + stateTimeoutValue[1] = 2; + stateTransitionOnTimeout[1] = "Ready"; + stateTransitionOnNotLoaded[1] = "Deactivate"; + stateTransitionOnNoAmmo[1] = "NoAmmo"; + + stateName[2] = "Ready"; + stateTransitionOnNotLoaded[2] = "Deactivate"; + stateTransitionOnTriggerDown[2] = "Fire"; + stateTransitionOnNoAmmo[2] = "NoAmmo"; + + stateName[3] = "Fire"; + stateTransitionOnTimeout[3] = "Reload"; + stateTimeoutValue[3] = 0.3; + stateFire[3] = true; + stateRecoil[3] = LightRecoil; + stateAllowImageChange[3] = false; + stateSequence[3] = "Fire"; + stateSound[3] = MBLFireSound; + stateScript[3] = "onFire"; + + stateName[4] = "Reload"; + stateTimeoutValue[4] = 3.5; + stateAllowImageChange[4] = false; + stateSequence[4] = "Reload"; + stateTransitionOnTimeout[4] = "Ready"; + stateTransitionOnNotLoaded[4] = "Deactivate"; + stateTransitionOnNoAmmo[4] = "NoAmmo"; + + stateName[5] = "Deactivate"; + stateSequence[5] = "Activate"; + stateDirection[5] = false; + stateTimeoutValue[5] = 2; + stateTransitionOnLoaded[5] = "ActivateReady"; + stateTransitionOnTimeout[5] = "Dead"; + + stateName[6] = "Dead"; + stateTransitionOnLoaded[6] = "ActivateReady"; + + stateName[7] = "NoAmmo"; + stateTransitionOnAmmo[7] = "Reload"; + stateSequence[7] = "NoAmmo"; +}; + +datablock TurretImageData(SwarmDiscTurretBarrel1):SwarmDiscTurretBarrel +{ + shapeFile = "turret_AA_large.dts";//weapon_mortar.dts"; + item = Mortar; + offset = "-0.7 -0.04 -0.45"; + rotation = "0 1 0 -90"; +}; + + +function SwarmDiscTurretBarrel::onMount(%this, %obj, %slot) +{ +%mount1 = "SwarmDiscTurretBarrel1"; +%mount2 = "MtcTurretCore"; +%obj.schedule(2000,"mountImage",%mount1,1,true); +%obj.mountImage(%mount2,2,true); +} + + +function SwarmDiscTurretBarrel::onFire(%data,%obj,%slot) +{ +for (%i = 0; %i < 5;%i++) + { +%obj.currentbarrel = !%obj.currentbarrel; +%slot = %obj.currentbarrel; + %p = Parent::onFire(%data, %obj, %slot); + if (%p) + { + MissileSet.add(%p); + + if (%obj.base.target) + { + %target = %obj.base.target; + } + else + %target = %obj.getLockedTarget(); + + %sign = GiveSign(%target); + if(%target) + { + %p.setObjectTarget(%sign); + } + else if(%obj.isLocked()) + %p.setPositionTarget(%obj.getLockedPosition()); + else + %p.setNoTarget(); + discoff(%p); + } + } + +} + +function SwarmDiscTurretBarrel1::onFire(%data,%obj,%slot) +{ +//Do nothing; +} + +function discoff(%p) +{ +if (!IsObject(%p)) +return ""; +if (!IsObject(%p.getTargetObject()) && IsObject(%p.disctarget)) + { + %p.setObjectTarget(%p.disctarget); + } +else if (IsObject(%p.getTargetObject())) + { + %p.disctarget = %p.getTargetObject(); + %p.setNoTarget(); + } +else + return ""; +schedule(getRandom()*1000+500,0,"discoff",%p); +} + diff --git a/scripts/MTC_level.cs b/scripts/MTC_level.cs new file mode 100644 index 0000000..8f5c715 --- /dev/null +++ b/scripts/MTC_level.cs @@ -0,0 +1,41 @@ +//Basic Levels; + +//These make up the spawning behaviour of the mtc weapon types +//Only starting ideas for now +//Changes are culmative + +//Only targeting lasers +function MTCLevel0() +{ +$MTCCHANGE::weapon[0] = "target"; +$MTCCHANGE::change[0] = 1; +$MTCCHANGE::totchange = 1; +$MTCCHANGE::count = 1; +} + +//9 targeting lasers +//1 blaster +function MTCLevel1() +{ +$MTCCHANGE::weapon[0] = "target"; +$MTCCHANGE::change[0] = 9; +$MTCCHANGE::weapon[0] = "blaster"; +$MTCCHANGE::change[0] = 10; +$MTCCHANGE::totchange = 10; +$MTCCHANGE::count = 2; +} + +//8 targeting lasers +//2 blasters +//1 grenades +function MTCLevel2() +{ +$MTCCHANGE::weapon[0] = "target"; +$MTCCHANGE::change[0] = 8; +$MTCCHANGE::weapon[0] = "blaster"; +$MTCCHANGE::change[0] = 10; +$MTCCHANGE::weapon[0] = "grenade"; +$MTCCHANGE::change[0] = 11; +$MTCCHANGE::totchange = 11; +$MTCCHANGE::count = 3; +} \ No newline at end of file diff --git a/scripts/MTC_weap.cs b/scripts/MTC_weap.cs new file mode 100644 index 0000000..4faa6c0 --- /dev/null +++ b/scripts/MTC_weap.cs @@ -0,0 +1,1334 @@ +$MtcWeaponCount = 15; +///Light +$MtcWeapontype[0] = "blaster"; +$MtcWeapontype[1] = "disc"; +$MtcWeapontype[2] = "laser"; +///Medium +$MtcWeapontype[3] = "grenade"; +$MtcWeapontype[4] = "plasma"; +$MtcWeapontype[5] = "chain"; +///Heavy +$MtcWeapontype[6] = "missile"; +$MtcWeapontype[7] = "mortar"; +$MtcWeapontype[8] = "fusion"; +///No damage +$MtcWeapontype[9] = "nerf"; +$MtcWeapontype[10] = "target"; +///Ion weapons +$MtcWeapontype[11] = "IonMissile"; +$MtcWeapontype[12] = "IonBeam"; +//Excotic weapons +$MtcWeapontype[13] = "Tractor"; +$MtcWeapontype[14] = "SwarmDisc"; + +$mtcWeaponSize["nerf"] = "light"; +$mtcWeaponSize["blaster"] = "light"; +$mtcWeaponSize["disc"] = "light"; +$mtcWeaponSize["laser"] = "light"; +$mtcWeaponSize["target"] = "light"; +$mtcWeaponSize["grenade"] = "medium"; +$mtcWeaponSize["plasma"] = "medium"; +$mtcWeaponSize["chain"] = "medium"; +$mtcWeaponSize["Missile"] = "heavy"; +$mtcWeaponSize["Mortar"] = "heavy"; +$mtcWeaponSize["Fusion"] = "heavy"; +$mtcWeaponSize["IonMissile"] = "heavy"; +$mtcWeaponSize["IonBeam"] = "heavy"; +$mtcWeaponSize["Tractor"] = "light"; +$mtcWeaponSize["SwarmDisc"] = "heavy"; + +$mtcScore["nerf"] = 1; +$mtcScore["blaster"] = 5; +$mtcScore["disc"] = 8; +$mtcScore["laser"] = 8; +$mtcScore["target"] = 1; +$mtcScore["grenade"] = 5; +$mtcScore["plasma"] = 5; +$mtcScore["chain"] = 10; +$mtcScore["Missile"] = 15; +$mtcScore["Mortar"] = 25; +$mtcScore["Fusion"] = 25; +$mtcScore["IonMissile"] = 15; +$mtcScore["Ionbeam"] = 20; +$mtcScore["Tractor"] = 10; +$mtcScore["SwarmDisc"] = 30; + +$MtcBaseChange["nerf"] = 1; +$MtcBaseChange["blaster"] = 1;//6; +$MtcBaseChange["disc"] = 1;//8; +$MtcBaseChange["laser"] = 1;//4; +$MtcBaseChange["target"] = 1; +$MtcBaseChange["grenade"] = 1;//8; +$MtcBaseChange["plasma"] = 1;//8; +$MtcBaseChange["chain"] = 1;//8; +$MtcBaseChange["Missile"] = 1;//4; +$MtcBaseChange["Mortar"] = 1;//2; +$MtcBaseChange["Fusion"] = 1;//4; +$MtcBaseChange["IonMissile"] = 1;//2; +$MtcBaseChange["Ionbeam"] = 1; +$MtcBaseChange["Tractor"] = 1;//2; +$MtcBaseChange["SwarmDisc"] = 1; + +$MtcWeaponBlock["nerf"] = 1; + +function MtcMakeChangeList() +{ +$MTCCHANGE::count=0; +$MTCCHANGE::totchange=0; +for (%i=0;%i< $MtcWeaponCount;%i++) + { + %weapon = $MtcWeapontype[%i]; + if (!$MtcWeaponBlock[%weapon] && $MtcBaseChange[%weapon]) + { + $MTCCHANGE::weapon[%i] =%weapon; + $MTCCHANGE::change[%i] = $MTCCHANGE::totchange + $MtcBaseChange[%weapon]; + $MTCCHANGE::totchange =$MTCCHANGE::change[%i]; + $MTCCHANGE::count++; + } + } +} + +function MtcRandomWeapon() +{ +%count = $MTCCHANGE::count; +if (!%count) + MTCmakeChangelist(); +%r = getRandom()*$MTCCHANGE::totchange; + +for (%i=0; %i<%count; %i++) + { + if ($MTCCHANGE::change[%i]>%r) + return $MTCCHANGE::weapon[%i]; + } +return $MTCCHANGE::weapon[0]; +} + + +datablock ShapeBaseImageData(MtcTurretCore) +{ + shapeFile = "pack_barrel_elf.dts";//weapon_missile.dts"; + + item = MissileLauncher; + + offset = "0 0.5 -0.7"; + rotation = "1 0 0 90"; +}; + + +///////////////////////////////////////////// +////////////////Fusion/////////////////////// +///////////////////////////////////////////// + + +datablock TurretImageData(FusionTurretBarrel) +{ + shapeFile = "turret_fusion_large.dts"; + item = PlasmaBarrelLargePack; + + projectile = PlasmaBarrelBolt; + projectileType = LinearFlareProjectile; + usesEnergy = true; + fireEnergy = 10; + minEnergy = 10; + emap = true; + + offset = "-0.7 -0.04 -0.4"; + rotation = "0 1 0 90"; + + + // Turret parameters + activationMS = 1000; + deactivateDelayMS = 1500; + thinkTimeMS = 200; + degPerSecTheta = 300; + degPerSecPhi = 500; + attackRadius = 120; + + // State transitions + stateName[0] = "Activate"; + stateTransitionOnNotLoaded[0] = "Dead"; + stateTransitionOnLoaded[0] = "ActivateReady"; + + stateName[1] = "ActivateReady"; + stateSequence[1] = "Activate"; + stateSound[1] = PBLSwitchSound; + stateTimeoutValue[1] = 1; + stateTransitionOnTimeout[1] = "Ready"; + stateTransitionOnNotLoaded[1] = "Deactivate"; + stateTransitionOnNoAmmo[1] = "NoAmmo"; + + stateName[2] = "Ready"; + stateTransitionOnNotLoaded[2] = "Deactivate"; + stateTransitionOnTriggerDown[2] = "Fire"; + stateTransitionOnNoAmmo[2] = "NoAmmo"; + + stateName[3] = "Fire"; + stateTransitionOnTimeout[3] = "Reload"; + stateTimeoutValue[3] = 0.15; //0.3 + stateFire[3] = true; + stateRecoil[3] = LightRecoil; + stateAllowImageChange[3] = false; + stateSequence[3] = "Fire"; + stateSound[3] = PBLFireSound; + stateScript[3] = "onFire"; + + stateName[4] = "Reload"; + stateTimeoutValue[4] = 0.4; //0.8 + stateAllowImageChange[4] = false; + stateSequence[4] = "Reload"; + stateTransitionOnTimeout[4] = "Ready"; + stateTransitionOnNotLoaded[4] = "Deactivate"; + stateTransitionOnNoAmmo[4] = "NoAmmo"; + + stateName[5] = "Deactivate"; + stateSequence[5] = "Activate"; + stateDirection[5] = false; + stateTimeoutValue[5] = 1; + stateTransitionOnLoaded[5] = "ActivateReady"; + stateTransitionOnTimeout[5] = "Dead"; + + stateName[6] = "Dead"; + stateTransitionOnLoaded[6] = "ActivateReady"; + + stateName[7] = "NoAmmo"; + stateTransitionOnAmmo[7] = "Reload"; + stateSequence[7] = "NoAmmo"; +}; + +datablock TurretImageData(FusionTurretBarrel1) +{ +shapeFile = "turret_fusion_large.dts"; +item = PlasmaBarrelLargePack; +offset = "0.7 -0.04 -0.4"; +rotation = "0 1 0 -90"; +}; + +function FusionTurretBarrel::onMount(%this, %obj, %slot) +{ +%mount1 = "FusionTurretBarrel1"; +%mount2 = "MtcTurretCore"; +%obj.schedule(2000,"mountImage",%mount1,1,true); +%obj.mountImage(%mount2,2,true); +} + +function FusionTurretBarrel::onFire( %data, %obj, %slot ) +{ +Parent::onFire(%data,%obj,%obj.currentbarrel); +%obj.currentbarrel = !%obj.currentbarrel; +} + +function FusionTurretBarrel1::onFire( %data, %obj, %slot ) +{ +///Do nothing; +} + +///////////////////////////////////////////// +////////////////Mortar/////////////////////// +///////////////////////////////////////////// + + + +datablock TurretImageData(MortarTurretBarrel) +{ + shapeFile = "turret_mortar_large.dts";//weapon_mortar.dts"; + item = Mortar; + mountPoint = 0; + //ammo = MortarAmmo; + + emap = true; + + projectileSpread = 8/1000; + + usesEnergy = true; + fireEnergy = 4; + minEnergy = 4; + + yawVariance = 30.0; // these will smooth out the elf tracking code. + pitchVariance = 30.0; // more or less just tolerances + + offset = "-0.7 -0.04 -0.45"; + rotation = "0 1 0 90"; + + // Turret parameters + activationMS = 3000; + deactivateDelayMS = 5000; + thinkTimeMS = 2000; + degPerSecTheta = 2080; + degPerSecPhi = 2080; + attackRadius = 800; + + projectile = MortarShot; + projectileType = GrenadeProjectile; + + stateName[0] = "Activate"; + stateTransitionOnTimeout[0] = "ActivateReady"; + stateTimeoutValue[0] = 0.5; + stateSequence[0] = "Activate"; + stateSound[0] = MortarSwitchSound; + + stateName[1] = "ActivateReady"; + stateTransitionOnLoaded[1] = "Ready"; + stateTransitionOnNoAmmo[1] = "NoAmmo"; + + stateName[2] = "Ready"; + stateTransitionOnNoAmmo[2] = "NoAmmo"; + stateTransitionOnTriggerDown[2] = "Fire"; + //stateSound[2] = MortarIdleSound; + + stateName[3] = "Fire"; + stateSequence[3] = "Recoil"; + stateTransitionOnTimeout[3] = "Reload"; + stateTimeoutValue[3] = 0.4; // 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] = 1.0; //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"; +}; + +datablock TurretImageData(MortarTurretBarrel1):MortarTurretBarrel +{ + shapeFile = "turret_mortar_large.dts";//weapon_mortar.dts"; + item = Mortar; + mountPoint = 0; + offset = "0.7 -0.04 -0.45"; + rotation = "0 1 0 -90"; +}; + + +function MortarTurretBarrel::onMount(%this, %obj, %slot) +{ +%mount1 = "MortarTurretBarrel1"; +%mount2 = "MtcTurretCore"; +%obj.schedule(2000,"mountImage",%mount1,1,true); +%obj.mountImage(%mount2,2,true); +} + + +function MortarTurretBarrel::onFire(%data,%obj,%slot) +{ +Parent::onFire(%data,%obj,%obj.currentbarrel); +%obj.currentbarrel = !%obj.currentbarrel; +} + +function MortarTurretBarrel1::onFire(%data,%obj,%slot) +{ +///Do nothing; +} + + +///////////////////////////////////////////// +////////////////Blaster////////////////////// +///////////////////////////////////////////// + + + + +datablock TurretImageData(blasterTurretBarrel) +{ + + shapeFile = "weapon_energy.dts"; + item = Blaster; + projectile = EnergyBolt; + projectileType = EnergyProjectile; + + usesEnergy = true; + fireEnergy = 4; + minEnergy = 4; + + yawVariance = 30.0; // these will smooth out the elf tracking code. + pitchVariance = 30.0; // more or less just tolerances + + offset = "0.05 -0.4 0"; + rotation = "0 1 0 90"; + + projectileSpread = 8/1000; + + // Turret parameters + activationMS = 3000; + deactivateDelayMS = 5000; + thinkTimeMS = 2000; + degPerSecTheta = 2080; + degPerSecPhi = 2080; + attackRadius = 800; + + stateName[0] = "Activate"; + stateTransitionOnTimeout[0] = "ActivateReady"; + stateTimeoutValue[0] = 0.5; + stateSequence[0] = "Activate"; + stateSound[0] = BlasterSwitchSound; + + stateName[1] = "ActivateReady"; + stateTransitionOnLoaded[1] = "Ready"; + stateTransitionOnNoAmmo[1] = "NoAmmo"; + + stateName[2] = "Ready"; + stateTransitionOnNoAmmo[2] = "NoAmmo"; + stateTransitionOnTriggerDown[2] = "Fire"; + + stateName[3] = "Fire"; + stateTransitionOnTimeout[3] = "Reload"; + stateTimeoutValue[3] = 0.3; + stateFire[3] = true; + stateRecoil[3] = NoRecoil; + stateAllowImageChange[3] = false; + stateSequence[3] = "Fire"; + stateSound[3] = BlasterFireSound; + stateScript[3] = "onFire"; + + stateName[4] = "Reload"; + stateTransitionOnNoAmmo[4] = "NoAmmo"; + stateTransitionOnTimeout[4] = "Ready"; + stateAllowImageChange[4] = false; + stateSequence[4] = "Reload"; + + stateName[5] = "NoAmmo"; + stateTransitionOnAmmo[5] = "Reload"; + stateSequence[5] = "NoAmmo"; + stateTransitionOnTriggerDown[5] = "DryFire"; + + stateName[6] = "DryFire"; + stateTimeoutValue[6] = 0.3; + stateSound[6] = BlasterDryFireSound; + stateTransitionOnTimeout[6] = "Ready"; +}; + +///////////////////////////////////////////// +////////////////Disc///////////////////////// +///////////////////////////////////////////// + + +datablock TurretImageData(DiscTurretBarrel) +{ + + shapeFile = "weapon_disc.dts"; + item = Disc; + //ammo = DiscAmmo; + + emap = true; + + projectileSpread = 4.0 / 1000.0; + + projectile = DiscProjectile; + projectileType = LinearProjectile; + + usesEnergy = true; + fireEnergy = 4; + minEnergy = 4; + + yawVariance = 30.0; // these will smooth out the elf tracking code. + pitchVariance = 30.0; // more or less just tolerances + + offset = "0 -0.2 0"; + rotation = "0 1 0 90"; + // Turret parameters + activationMS = 3000; + deactivateDelayMS = 5000; + thinkTimeMS = 2000; + degPerSecTheta = 2080; + degPerSecPhi = 2080; + attackRadius = 800; + + // State Data + stateName[0] = "Preactivate"; + stateTransitionOnLoaded[0] = "Activate"; + stateTransitionOnNoAmmo[0] = "NoAmmo"; + + stateName[1] = "Activate"; + stateTransitionOnTimeout[1] = "Ready"; + stateTimeoutValue[1] = 0.5; + stateSequence[1] = "Activated"; + stateSound[1] = DiscSwitchSound; + + stateName[2] = "Ready"; + stateTransitionOnNoAmmo[2] = "NoAmmo"; + stateTransitionOnTriggerDown[2] = "Fire"; + stateSequence[2] = "DiscSpin"; + stateSound[2] = DiscLoopSound; + + stateName[3] = "Fire"; + stateTransitionOnTimeout[3] = "Reload"; + stateTimeoutValue[3] = 1.25; + stateFire[3] = true; + stateRecoil[3] = LightRecoil; + stateAllowImageChange[3] = false; + stateSequence[3] = "Fire"; + stateScript[3] = "onFire"; + stateSound[3] = DiscFireSound; + + stateName[4] = "Reload"; + stateTransitionOnNoAmmo[4] = "NoAmmo"; + stateTransitionOnTimeout[4] = "Ready"; + stateTimeoutValue[4] = 0.5; // 0.25 load, 0.25 spinup + stateAllowImageChange[4] = false; + stateSequence[4] = "Reload"; + stateSound[4] = DiscReloadSound; + + stateName[5] = "NoAmmo"; + stateTransitionOnAmmo[5] = "Reload"; + stateSequence[5] = "NoAmmo"; + stateTransitionOnTriggerDown[5] = "DryFire"; + + stateName[6] = "DryFire"; + stateSound[6] = DiscDryFireSound; + stateTimeoutValue[6] = 1.0; + stateTransitionOnTimeout[6] = "NoAmmo"; + +}; + + + + +///////////////////////////////////////////// +////////////////Missile////////////////////// +///////////////////////////////////////////// + + + +datablock TurretImageData(MissileTurretBarrel) +{ + + shapeFile = "turret_missile_large.dts";//weapon_missile.dts"; + item = MissileLauncher; + //ammo = MissileLauncherAmmo; + armThread = lookms; + emap = true; + + projectile = ShoulderMissile; + projectileType = SeekerProjectile; + + isSeeker = true; + seekRadius = 900; + maxSeekAngle = 90; + seekTime = 2.5; //5.0 + minSeekHeat = 0.0; // the heat that must be present on a target to lock it. + yawVariance = 30.0; // these will smooth out the elf tracking code. + pitchVariance = 30.0; // more or less just tolerances + + usesEnergy = true; + fireEnergy = 4; + minEnergy = 4; + projectileSpread = 8/1000; + + offset = "-0.7 -0.04 -0.45"; + rotation = "0 1 0 70"; + + + // only target objects outside this range + minTargetingDistance = 4; + + // Turret parameters + activationMS = 250; + deactivateDelayMS = 500; + thinkTimeMS = 200; + degPerSecTheta = 580; + degPerSecPhi = 1080; + attackRadius = 500; + + // State transitions + stateName[0] = "Activate"; + stateTransitionOnNotLoaded[0] = "Dead"; + stateTransitionOnLoaded[0] = "ActivateReady"; + + stateName[1] = "ActivateReady"; + stateSequence[1] = "Activate"; + stateSound[1] = MBLSwitchSound; + stateTimeoutValue[1] = 2; + stateTransitionOnTimeout[1] = "Ready"; + stateTransitionOnNotLoaded[1] = "Deactivate"; + stateTransitionOnNoAmmo[1] = "NoAmmo"; + + stateName[2] = "Ready"; + stateTransitionOnNotLoaded[2] = "Deactivate"; + stateTransitionOnTriggerDown[2] = "Fire"; + stateTransitionOnNoAmmo[2] = "NoAmmo"; + + stateName[3] = "Fire"; + stateTransitionOnTimeout[3] = "Reload"; + stateTimeoutValue[3] = 0.15; //0.3 + stateFire[3] = true; + stateRecoil[3] = LightRecoil; + stateAllowImageChange[3] = false; + stateSequence[3] = "Fire"; + stateSound[3] = MBLFireSound; + stateScript[3] = "onFire"; + + stateName[4] = "Reload"; + stateTimeoutValue[4] = 1.75; //3.5 + stateAllowImageChange[4] = false; + stateSequence[4] = "Reload"; + stateTransitionOnTimeout[4] = "Ready"; + stateTransitionOnNotLoaded[4] = "Deactivate"; + stateTransitionOnNoAmmo[4] = "NoAmmo"; + + stateName[5] = "Deactivate"; + stateSequence[5] = "Activate"; + stateDirection[5] = false; + stateTimeoutValue[5] = 2; + stateTransitionOnLoaded[5] = "ActivateReady"; + stateTransitionOnTimeout[5] = "Dead"; + + stateName[6] = "Dead"; + stateTransitionOnLoaded[6] = "ActivateReady"; + + stateName[7] = "NoAmmo"; + stateTransitionOnAmmo[7] = "Reload"; + stateSequence[7] = "NoAmmo"; +}; + +datablock TurretImageData(MissileTurretBarrel1):MissileTurretBarrel +{ + shapeFile = "turret_missile_large.dts";//weapon_missile.dts"; + item = MissileLauncher; + offset = "0.7 -0.04 -0.45"; + rotation = "0 1 0 -70"; +}; + + + +function MissileTurretBarrel::onMount(%this, %obj, %slot) +{ +%mount1 = "MissileTurretBarrel1"; +%mount2 = "MtcTurretCore"; +%obj.schedule(2000,"mountImage",%mount1,1,true); +%obj.mountImage(%mount2,2,true); +} + + +function MissileTurretBarrel::onFire(%data,%obj,%slot) +{ +%obj.currentbarrel = !%obj.currentbarrel; +%slot = %obj.currentbarrel; + %p = Parent::onFire(%data, %obj, %slot); + MissileSet.add(%p); + + //echo(%p.getDatablock.dynamictype); + + if (%obj.base.target) + { + if (%obj.base.target.getheat()>0.2) + { + %target = %obj.base.target; + } + } + else + %target = %obj.getLockedTarget(); + + + if(%target) + %p.setObjectTarget(%target); + else if(%obj.isLocked()) + %p.setPositionTarget(%obj.getLockedPosition()); + else + %p.setNoTarget(); +} + +function MissileTurretBarrel1::onFire(%data,%obj,%slot) +{ + //Do nothing +} + +///////////////////////////////////////////// +////////////////IonMissile/////////////////// +///////////////////////////////////////////// + + +datablock TurretImageData(ionMissileTurretBarrel):MissileTurretBarrel +{ +projectile = IonMissile; +projectileType = SeekerProjectile; +projectileSpread = 8/1000; + +offset = "0 -0.2 -0.3"; + rotation = "0 1 0 00"; + yawVariance = 30.0; // these will smooth out the elf tracking code. + pitchVariance = 30.0; // more or less just tolerances +}; + + +function IonMissileTurretBarrel::onFire(%data,%obj,%slot) +{ + %p = Parent::onFire(%data, %obj, %slot); + MissileSet.add(%p); + + //echo(%p.getDatablock.dynamictype); + + + if (%obj.base.target) + { + if (%obj.base.target.getheat()>0.2) + { + %target = %obj.base.target; + } + } + else + %target = %obj.getLockedTarget(); + + if(%target) + %p.setObjectTarget(%target); + else if(%obj.isLocked()) + %p.setPositionTarget(%obj.getLockedPosition()); + else + %p.setNoTarget(); +} + + + +///////////////////////////////////////////// +////////////////IonBeam////////////////////// +///////////////////////////////////////////// + + + +datablock TurretImageData(ionbeamTurretBarrel):LaserTurretBarrel +{ +shapeFile = "turret_Elf_large.dts";//weapon_missile.dts"; +offset = "-0.7 -0.04 -0.4"; +rotation = "0 1 0 90"; +projectile = ShockBeam2; +projectileType = SniperProjectileData; + + usesEnergy = true; + fireEnergy = 50.0; + minEnergy = 50.0; + + yawVariance = 30.0; // these will smooth out the elf tracking code. + pitchVariance = 30.0; // more or less just tolerances + // Turret parameters + activationMS = 500; + deactivateDelayMS = 100; + thinkTimeMS = 100; + degPerSecTheta = 580; + degPerSecPhi = 960; + attackRadius = 500; + + + yawVariance = 30.0; // these will smooth out the elf tracking code. + pitchVariance = 30.0; // more or less just tolerances + + + // State transiltions + stateName[0] = "Activate"; + stateTransitionOnNotLoaded[0] = "Dead"; + stateTransitionOnLoaded[0] = "ActivateReady"; + + stateName[1] = "ActivateReady"; + stateSequence[1] = "Activate"; + stateSound[1] = EBLSwitchSound; + stateTimeoutValue[1] = 1; + stateTransitionOnTimeout[1] = "Ready"; + stateTransitionOnNotLoaded[1] = "Deactivate"; + stateTransitionOnNoAmmo[1] = "NoAmmo"; + + stateName[2] = "Ready"; + stateTransitionOnNotLoaded[2] = "Deactivate"; + stateTransitionOnTriggerDown[2] = "Fire"; + stateTransitionOnNoAmmo[2] = "NoAmmo"; + + stateName[3] = "Fire"; + stateFire[3] = true; + stateRecoil[3] = LightRecoil; + stateAllowImageChange[3] = false; + stateSequence[3] = "Fire"; + stateSound[3] = EBLFireSound; + stateScript[3] = "onFire"; + stateTransitionOnTriggerUp[3] = "Deconstruction"; + stateTransitionOnNoAmmo[3] = "Deconstruction"; + + stateName[4] = "Reload"; + stateTimeoutValue[4] = 0.01; + stateAllowImageChange[4] = false; + stateSequence[4] = "Reload"; + stateTransitionOnTimeout[4] = "Ready"; + stateTransitionOnNotLoaded[4] = "Deactivate"; + stateTransitionOnNoAmmo[4] = "NoAmmo"; + + stateName[5] = "Deactivate"; + stateSequence[5] = "Activate"; + stateDirection[5] = false; + stateTimeoutValue[5] = 1; + stateTransitionOnLoaded[5] = "ActivateReady"; + stateTransitionOnTimeout[5] = "Dead"; + + stateName[6] = "Dead"; + stateTransitionOnLoaded[6] = "ActivateReady"; + + stateName[7] = "NoAmmo"; + stateTransitionOnAmmo[7] = "Reload"; + stateSequence[7] = "NoAmmo"; + + stateName[8] = "Deconstruction"; + stateScript[8] = "deconstruct"; + stateTransitionOnNoAmmo[8] = "NoAmmo"; + stateTransitionOnTimeout[8] = "Reload"; + stateTimeoutValue[8] = 0.1; +}; + + +datablock TurretImageData(ionbeamTurretBarrel1):ionbeamTurretBarrel +{ +shapeFile = "turret_Elf_large.dts";//weapon_missile.dts"; +offset = "0.7 -0.04 -0.4"; +rotation = "0 1 0 -90"; +}; + +function IonBeamTurretBarrel::onMount(%this, %obj, %slot) +{ +%mount1 = "IonBeamTurretBarrel1"; +%mount2 = "MtcTurretCore"; +%obj.schedule(2000,"mountImage",%mount1,1,true); +%obj.mountImage(%mount2,2,true); +} + +function ionbeamTurretBarrel::onFire( %data, %obj, %slot ) +{ +%obj.currentbarrel = !%obj.currentbarrel; +%slot = %obj.currentbarrel; +%vec = %obj.getMuzzleVector(%slot); +%vec = VectorMiss(%vec,80); + +%energy = %obj.getEnergyLevel(); + +%p = discharge2(%obj.getMuzzlePoint(%slot),%vec,0,%obj); + + %p.setEnergyPercentage(1); + %obj.lastProjectile = %p; + MissionCleanup.add(%p); + %obj.setEnergyLevel(%energy - %data.fireEnergy); +} + +function ionbeamTurretBarrel1::onFire( %data, %obj, %slot ) +{ +///Do nothing; +} + + +///////////////////////////////////////////// +////////////////////NERF///////////////////// +///////////////////////////////////////////// + + +datablock TurretImageData(NerfTurretBarrel) +{ + + shapeFile = "weapon_energy.dts"; + item = NerfGun; + + projectile = NerfBolt; + projectileType = LinearFlareProjectile; + + usesEnergy = true; + fireEnergy = 4; + minEnergy = 4; + + yawVariance = 30.0; // these will smooth out the elf tracking code. + pitchVariance = 30.0; // more or less just tolerances + + offset = "0.05 -0.4 0"; + rotation = "0 1 0 90"; + + // Turret parameters + activationMS = 3000; + deactivateDelayMS = 5000; + thinkTimeMS = 2000; + degPerSecTheta = 2080; + degPerSecPhi = 2080; + attackRadius = 800; + + stateName[0] = "Activate"; + stateTransitionOnTimeout[0] = "ActivateReady"; + stateTimeoutValue[0] = 0.5; + stateSequence[0] = "Activate"; + stateSound[0] = BlasterSwitchSound; + + stateName[1] = "ActivateReady"; + stateTransitionOnLoaded[1] = "Ready"; + stateTransitionOnNoAmmo[1] = "NoAmmo"; + + stateName[2] = "Ready"; + stateTransitionOnNoAmmo[2] = "NoAmmo"; + stateTransitionOnTriggerDown[2] = "Fire"; + + stateName[3] = "Fire"; + stateTransitionOnTimeout[3] = "Reload"; + stateTimeoutValue[3] = 0.3; + stateFire[3] = true; + stateRecoil[3] = NoRecoil; + stateAllowImageChange[3] = false; + stateSequence[3] = "Fire"; + stateSound[3] = NerfGunFireSound; + stateScript[3] = "onFire"; + + stateName[4] = "Reload"; + stateTransitionOnNoAmmo[4] = "NoAmmo"; + stateTransitionOnTimeout[4] = "Ready"; + stateAllowImageChange[4] = false; + stateSequence[4] = "Reload"; + + stateName[5] = "NoAmmo"; + stateTransitionOnAmmo[5] = "Reload"; + stateSequence[5] = "NoAmmo"; + stateTransitionOnTriggerDown[5] = "DryFire"; + + stateName[6] = "DryFire"; + stateTimeoutValue[6] = 0.3; + stateSound[6] = NerfGunDryFireSound; + stateTransitionOnTimeout[6] = "Ready"; +}; + + + +///////////////////////////////////////////// +////////////////GRENDADE///////////////////// +///////////////////////////////////////////// + + +datablock TurretImageData(GrenadeTurretBarrel) +{ + + shapeFile = "weapon_grenade_launcher.dts"; + item = GrenadeLauncher; + + emap = true; + + + usesEnergy = true; + fireEnergy = 1.0; + minEnergy = 1.0; + + yawVariance = 30.0; // these will smooth out the elf tracking code. + pitchVariance = 30.0; // more or less just tolerances + +offset = "-0.3 0 -0.05"; +rotation = "0 1 0 90"; + // Turret parameters + activationMS = 3000; + deactivateDelayMS = 5000; + thinkTimeMS = 2000; + degPerSecTheta = 2080; + degPerSecPhi = 2080; + attackRadius = 800; + + projectileSpread = 8/1000; + + projectile = BasicGrenade; + projectileType = GrenadeProjectile; + + stateName[0] = "Activate"; + stateTransitionOnTimeout[0] = "ActivateReady"; + stateTimeoutValue[0] = 0.5; + stateSequence[0] = "Activate"; + stateSound[0] = GrenadeSwitchSound; + + stateName[1] = "ActivateReady"; + stateTransitionOnLoaded[1] = "Ready"; + stateTransitionOnNoAmmo[1] = "NoAmmo"; + + stateName[2] = "Ready"; + stateTransitionOnNoAmmo[2] = "NoAmmo"; + stateTransitionOnTriggerDown[2] = "Fire"; + + 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] = GrenadeFireSound; + + stateName[4] = "Reload"; + stateTransitionOnNoAmmo[4] = "NoAmmo"; + stateTransitionOnTimeout[4] = "Ready"; + stateTimeoutValue[4] = 0.5; + stateAllowImageChange[4] = false; + stateSequence[4] = "Reload"; + stateSound[4] = GrenadeReloadSound; + + stateName[5] = "NoAmmo"; + stateTransitionOnAmmo[5] = "Reload"; + stateSequence[5] = "NoAmmo"; + stateTransitionOnTriggerDown[5] = "DryFire"; + + stateName[6] = "DryFire"; + stateSound[6] = GrenadeDryFireSound; + stateTimeoutValue[6] = 1.5; + stateTransitionOnTimeout[6] = "NoAmmo"; +}; + + +///////////////////////////////////////////// +////////////////LASER//////////////////////// +///////////////////////////////////////////// + + +datablock TurretImageData(LaserTurretBarrel) +{ + + shapeFile = "weapon_sniper.dts"; + item = SniperRifle; + projectile = BasicSniperShot; + projectileType = SniperProjectile; + + armThread = looksn; + + usesEnergy = true; + minEnergy = 30.0; + fireEnergy = 20.0; + +rotation = "0 1 0 90"; +offset = "0 -0.12 0"; + + yawVariance = 30.0; // these will smooth out the elf tracking code. + pitchVariance = 30.0; // more or less just tolerances + + // Turret parameters + activationMS = 3000; + deactivateDelayMS = 5000; + thinkTimeMS = 2000; + degPerSecTheta = 2080; + degPerSecPhi = 2080; + attackRadius = 800; + + + stateName[0] = "Activate"; + stateTransitionOnTimeout[0] = "ActivateReady"; + stateSound[0] = SniperRifleSwitchSound; + stateTimeoutValue[0] = 0.5; + stateSequence[0] = "Activate"; + + stateName[1] = "ActivateReady"; + stateTransitionOnLoaded[1] = "Ready"; + stateTransitionOnNoAmmo[1] = "NoAmmo"; + + stateName[2] = "Ready"; + stateTransitionOnNoAmmo[2] = "NoAmmo"; + stateTransitionOnTriggerDown[2] = "CheckWet"; + + stateName[3] = "Fire"; + stateTransitionOnTimeout[3] = "Reload"; + stateTimeoutValue[3] = 0.5; + stateFire[3] = true; + stateAllowImageChange[3] = false; + stateSequence[3] = "Fire"; + stateScript[3] = "onFire"; + + stateName[4] = "Reload"; + stateTransitionOnTimeout[4] = "Ready"; + stateTimeoutValue[4] = 0.5; + stateAllowImageChange[4] = false; + + stateName[5] = "CheckWet"; + stateTransitionOnWet[5] = "DryFire"; + stateTransitionOnNotWet[5] = "Fire"; + + stateName[6] = "NoAmmo"; + stateTransitionOnAmmo[6] = "Reload"; + stateTransitionOnTriggerDown[6] = "DryFire"; + stateSequence[6] = "NoAmmo"; + + stateName[7] = "DryFire"; + stateSound[7] = SniperRifleDryFireSound; + stateTimeoutValue[7] = 0.5; + stateTransitionOnTimeout[7] = "Ready"; +}; + +function LaserTurretBarrel::onFire( %data, %obj, %slot ) +{ +%vec = %obj.getMuzzleVector(%slot); + if(IsObject(%obj.base.target)) + { + %spread = %obj.base.target.getVelocity(); + %x = (getRandom() - 0.5) * 2 * 3.1415926 * %spread* getWord(%spread,0)/5000; + %y = (getRandom() - 0.5) * 2 * 3.1415926 * %spread* getWord(%spread,1)/5000; + %z = (getRandom() - 0.5) * 2 * 3.1415926 * %spread* getWord(%spread,2)/5000; + %mat = MatrixCreateFromEuler(%x @ " " @ %y @ " " @ %z); + %vec = MatrixMulVector(%mat, %vec); + } + + %energy = %obj.getEnergyLevel(); + %p = new (SniperProjectile)() { + dataBlock = BasicSniperShot; + initialDirection = %vec; + initialPosition = %obj.getMuzzlePoint(%slot); + sourceObject = %obj; + damageFactor = 1; + sourceSlot = %slot; + }; + + + + %p.setEnergyPercentage(1); + %obj.lastProjectile = %p; + MissionCleanup.add(%p); + %obj.setEnergyLevel(%energy - %data.fireEnergy); +} + +///////////////////////////////////////////// +////////////////TARGET/////////////////////// +///////////////////////////////////////////// + + +datablock TurretImageData(TargetTurretBarrel) +{ + + + shapeFile = "weapon_targeting.dts"; + item = TargetingLaser; + offset = "0 0 0"; + + projectile = BasicTargeter; + projectileType = TargetProjectile; + deleteLastProjectile = true; + + usesEnergy = true; + minEnergy = 10; +rotation = "0 1 0 90"; +offset = "0 -0.5 0"; + + // Turret parameters + activationMS = 3000; + deactivateDelayMS = 5000; + thinkTimeMS = 2000; + degPerSecTheta = 2080; + degPerSecPhi = 2080; + attackRadius = 800; + + yawVariance = 30.0; // these will smooth out the elf tracking code. + pitchVariance = 30.0; // more or less just tolerances + + stateName[0] = "Activate"; + stateSequence[0] = "Activate"; + stateSound[0] = TargetingLaserSwitchSound; + stateTimeoutValue[0] = 0.5; + stateTransitionOnTimeout[0] = "ActivateReady"; + + stateName[1] = "ActivateReady"; + stateTransitionOnAmmo[1] = "Ready"; + stateTransitionOnNoAmmo[1] = "NoAmmo"; + + stateName[2] = "Ready"; + stateTransitionOnNoAmmo[2] = "NoAmmo"; + stateTransitionOnTriggerDown[2] = "Fire"; + + stateName[3] = "Fire"; + stateEnergyDrain[3] = 3; + stateFire[3] = true; + stateAllowImageChange[3] = false; + stateScript[3] = "onFire"; + stateTransitionOnTriggerUp[3] = "Deconstruction"; + stateTransitionOnNoAmmo[3] = "Deconstruction"; + stateSound[3] = TargetingLaserPaintSound; + + stateName[4] = "NoAmmo"; + stateTransitionOnAmmo[4] = "Ready"; + + stateName[5] = "Deconstruction"; + stateScript[5] = "deconstruct"; + stateTransitionOnTimeout[5] = "Ready"; +}; + +///////////////////////////////////////////// +////////////////PLASMA/////////////////////// +///////////////////////////////////////////// +datablock TurretImageData(Plasmaturretbarrel) +{ + + shapeFile = "weapon_plasma.dts"; + item = Plasma; + ammo = PlasmaAmmo; + + + projectile = PlasmaBolt; + projectileType = LinearFlareProjectile; + + emap = true; + + usesEnergy = true; + fireEnergy = 1.0; + minEnergy = 1.0; + + offset = "-0.19 -0.24 0"; + rotation = "0 1 0 90"; + + yawVariance = 30.0; // these will smooth out the elf tracking code. + pitchVariance = 30.0; // more or less just tolerances + + // Turret parameters + activationMS = 3000; + deactivateDelayMS = 5000; + thinkTimeMS = 2000; + degPerSecTheta = 2080; + degPerSecPhi = 2080; + attackRadius = 800; + + projectileSpread = 16.0 / 1000.0; + + + stateName[0] = "Activate"; + stateTransitionOnTimeout[0] = "ActivateReady"; + stateTimeoutValue[0] = 0.5; + stateSequence[0] = "Activate"; + stateSound[0] = PlasmaSwitchSound; + + stateName[1] = "ActivateReady"; + stateTransitionOnLoaded[1] = "Ready"; + stateTransitionOnNoAmmo[1] = "NoAmmo"; + + stateName[2] = "Ready"; + stateTransitionOnNoAmmo[2] = "NoAmmo"; + stateTransitionOnTriggerDown[2] = "CheckWet"; + + stateName[3] = "Fire"; + stateTransitionOnTimeout[3] = "Reload"; + stateTimeoutValue[3] = 0.1; + stateFire[3] = true; + stateRecoil[3] = LightRecoil; + stateAllowImageChange[3] = false; + stateScript[3] = "onFire"; + stateEmitterTime[3] = 0.2; + stateSound[3] = PlasmaFireSound; + + stateName[4] = "Reload"; + stateTransitionOnNoAmmo[4] = "NoAmmo"; + stateTransitionOnTimeout[4] = "Ready"; + stateTimeoutValue[4] = 0.6; + stateAllowImageChange[4] = false; + stateSequence[4] = "Reload"; + stateSound[4] = PlasmaReloadSound; + + stateName[5] = "NoAmmo"; + stateTransitionOnAmmo[5] = "Reload"; + stateSequence[5] = "NoAmmo"; + stateTransitionOnTriggerDown[5] = "DryFire"; + + stateName[6] = "DryFire"; + stateSound[6] = PlasmaDryFireSound; + stateTimeoutValue[6] = 1.5; + stateTransitionOnTimeout[6] = "NoAmmo"; + + stateName[7] = "WetFire"; + stateSound[7] = PlasmaFireWetSound; + stateTimeoutValue[7] = 1.5; + stateTransitionOnTimeout[7] = "Ready"; + + stateName[8] = "CheckWet"; + stateTransitionOnWet[8] = "WetFire"; + stateTransitionOnNotWet[8] = "Fire"; +}; + +///////////////////////////////////////////// +////////////////CHAINGUN///////////////////// +///////////////////////////////////////////// + + +datablock TurretImageData(ChainturretBarrel) +{ + + shapeFile = "weapon_chaingun.dts"; + item = Chaingun; + + + usesEnergy = true; + fireEnergy = 0.1; + minEnergy = 10; + + offset = "-0.48 -0.05 0.1"; + rotation = "0 -1 0 90"; + + yawVariance = 30.0; // these will smooth out the elf tracking code. + pitchVariance = 30.0; // more or less just tolerances + + + projectile = ChaingunBullet; + projectileType = TracerProjectile; + emap = true; + + casing = ShellDebris; + shellExitDir = "1.0 0.3 1.0"; + shellExitOffset = "0.15 -0.56 -0.1"; + shellExitVariance = 15.0; + shellVelocity = 3.0; + + projectileSpread = 8/1000; + + // Turret parameters + activationMS = 1; + deactivateDelayMS = 1; + thinkTimeMS = 1; + degPerSecTheta = 2080; + degPerSecPhi = 2080; + attackRadius = 400; + + // State transitions +stateName[0] = "Activate"; +stateTransitionOnNotLoaded[0] = "Dead"; +stateTransitionOnLoaded[0] = "ActivateReady"; + +stateName[1] = "ActivateReady"; +stateSequence[1] = "Activate"; +stateSound[1] = PBLSwitchSound; +stateTimeoutValue[1] = 0.001; +stateTransitionOnTimeout[1] = "Ready"; +stateTransitionOnNotLoaded[1] = "Deactivate"; +stateTransitionOnNoAmmo[1] = "NoAmmo"; + +stateName[2] = "Ready"; +stateTransitionOnNotLoaded[2] = "Deactivate"; +stateTransitionOnTriggerDown[2] = "Fire"; +stateTransitionOnNoAmmo[2] = "NoAmmo"; + +// fire off about 2 quick shots +stateName[3] = "Fire"; +stateFire[3] = true; +stateAllowImageChange[3] = false; +stateSequence[3] = "Fire"; +stateSound[3] = ChaingunFireSound; +stateScript[3] = "onFire"; +stateTimeoutValue[3] = 0.05; //0.3 +stateTransitionOnTimeout[3] = "Fire"; +stateTransitionOnTriggerUp[3] = "Ready"; +// stateTransitionOnTriggerUp[3] = "Reload"; +stateTransitionOnNoAmmo[3] = "NoAmmo"; + +stateName[8] = "Reload"; +stateTimeoutValue[7] = 0.001; +stateAllowImageChange[8] = false; +stateSequence[8] = "Reload"; +stateTransitionOnTimeout[8] = "Ready"; +stateTransitionOnNotLoaded[8] = "Deactivate"; +stateTransitionOnNoAmmo[8] = "NoAmmo"; + +stateName[9] = "Deactivate"; +stateSequence[9] = "Activate"; +stateDirection[9] = false; +stateTimeoutValue[9] = 0.1; +stateTransitionOnLoaded[9] = "ActivateReady"; +stateTransitionOnTimeout[9] = "Dead"; + +stateName[10] = "Dead"; +stateTransitionOnLoaded[10] = "ActivateReady"; + +stateName[11] = "NoAmmo"; +stateTransitionOnAmmo[11] = "Reload"; +stateSequence[11] = "NoAmmo"; +}; diff --git a/scripts/OptionsDlg.cs b/scripts/OptionsDlg.cs new file mode 100644 index 0000000..fe0ceb7 --- /dev/null +++ b/scripts/OptionsDlg.cs @@ -0,0 +1,2763 @@ +//------------------------------------------------------------------------------ +// +// OptionsDlg.cs +// +//------------------------------------------------------------------------------ +$max_screenerror = 25; +$min_TSScreenError = 2; +$max_TSScreenError = 20; +$min_TSDetailAdjust = 0.6; +$max_TSDetailAdjust = 1.0; +//------------------------------------------------------------------------------ +function OptionsDlg::onWake( %this ) +{ + OP_VideoPane.setVisible( false ); + OP_GraphicsPane.setVisible( false ); + OP_TexturesPane.setVisible( false ); + OP_SoundPane.setVisible( false ); + OP_VoicePane.setVisible( false ); + OP_ControlsPane.setVisible( false ); + OP_NetworkPane.setVisible( false ); + OP_GamePane.setVisible( false ); + + OP_VideoTab.setValue( false ); + OP_GraphicsTab.setValue( false ); + OP_TexturesTab.setValue( false ); + OP_SoundTab.setValue( false ); + OP_VoiceTab.setValue( false ); + OP_ControlsTab.setValue( false ); + OP_NetworkTab.setValue( false ); + OP_GameTab.setValue( false ); + + // Initialize the Video Pane controls: + // First the Video Driver menu: + %buffer = getDisplayDeviceList(); + %count = getFieldCount( %buffer ); + for ( %i = 0; %i < %count; %i++ ) + OP_VideoDriverMenu.add( getField( %buffer, %i ), %i ); + + // Select the current device: + OP_FullScreenTgl.setValue( $pref::Video::fullScreen ); + + %selId = OP_VideoDriverMenu.findText( $pref::Video::displayDevice ); + if ( %selId == -1 ) + %selId = 0; // How did THAT happen? + OP_VideoDriverMenu.setSelected( %selId ); + OP_VideoDriverMenu.onSelect( %selId, "" ); + OP_FullScreenTgl.onAction(); + + OP_ApplyBtn.setActive( false ); + + // Initialize the Graphics Options controls: + OptionsDlg::deviceDependent( %this ); + + // Radeon cards don't switch color depth good until they release their beta drivers which fix this problem. + if( $RadeonRenderer == true ) + OP_BPPMenu.setActive( false ); + + OP_GammaSlider.setValue( $pref::OpenGL::gammaCorrection ); + OP_GammaSlider.setActive( $Video::setGammaCorrectionSupported ); + + OP_TerrainSlider.setValue( $max_screenerror - $pref::Terrain::screenError ); + OP_ShapeSlider.setValue( ( $max_TSScreenError - $pref::TS::screenError ) / ( $max_TSScreenError - $min_TSScreenError ) ); + OP_ShadowSlider.setValue( $pref::Shadows ); + OP_InteriorDetailSlider.setValue( $pref::Interior::detailAdjust ); + OP_VisibleDistanceSlider.setValue( $pref::VisibleDistanceMod ); + OP_ParticleDensitySlider.setValue( 4.0 - $pref::ParticleDensity ); + OP_DynamicLightSlider.setValue( 100 - $pref::Interior::DynamicLightsClipPix ); + updateDynamicLightSliderState(); + OP_SkyDetailMenu.init(); + if ( !$pref::SkyOn ) + %selId = 5; + else if ( $pref::numCloudLayers >= 0 && $pref::numCloudLayers < 4 ) + %selId = 4 - $pref::numCloudLayers; + else + %selId = 1; + OP_SkyDetailMenu.setSelected( %selId ); + OP_SkyDetailMenu.setText( OP_SkyDetailMenu.getTextById( %selId ) ); + OP_PlayerRenderMenu.init(); + %selId = $pref::Player::renderMyPlayer | ( $pref::Player::renderMyItems << 1 ); + OP_PlayerRenderMenu.setSelected( %selId ); + OP_VertexLightTgl.setValue( $pref::Interior::VertexLighting ); + + // Initialize the Textures Options controls: + OP_TerrainTexSlider.setValue( 6 - $pref::Terrain::texDetail ); + + // We're using the noDrawArraysAlpha variable here because we've already + // gone gold (hard to add a new profiling variable). But the Voodoo2/3/3500 + // cards that have the 256x256 texture limitation (in OpenGL) also have the + // noDrawArraysAlpha hack on...so that works out nice + %mipRange = $pref::OpenGL::noDrawArraysAlpha ? 4.0 : 5.0; + OP_ShapeTexSlider.setValue( (5 - $pref::OpenGL::mipReduction) / %mipRange ); + OP_BuildingTexSlider.setValue( (5 - $pref::OpenGL::interiorMipReduction) / %mipRange ); + OP_SkyTexSlider.setValue( (5 - $pref::OpenGL::skyMipReduction) / %mipRange ); + if ( !isDemo() ) + OP_HiResSkinTgl.setValue( $pref::use512PlayerSkins ); + + // Initialize the Sound Options controls: + // provider menu + %count = alxGetContexti(ALC_PROVIDER_COUNT); + for(%i = 0; %i < %count; %i++) + OP_AudioProviderMenu.add(alxGetContextstr(ALC_PROVIDER_NAME, %i), %i); + %selId = alxGetContexti(ALC_PROVIDER); + OP_AudioProviderMenu.setSelected(%selId); + OP_AudioResetProvider.setActive(false); + + // environment provider: disable and uncheck if not an environment provider + %envProvider = audioIsEnvironmentProvider(alxGetContextstr(ALC_PROVIDER_NAME, %selId)); + + if(!%envProvider) + OP_AudioEnvironmentTgl.setValue(false); + OP_AudioEnvironmentTgl.setActive(%envProvider); + + // speaker menu + %count = alxGetContexti(ALC_SPEAKER_COUNT); + for(%i = 0; %i < %count; %i++) + OP_AudioSpeakerMenu.add(alxGetContextstr(ALC_SPEAKER_NAME, %i), %i); + %selId = alxGetContexti(ALC_SPEAKER); + OP_AudioSpeakerMenu.setSelected(%selId); + OP_AudioSpeakerMenu.onSelect(%selId, ""); + + OP_AudioFrequencyMenu.init(); + OP_AudioBitRateMenu.init(); + OP_AudioChannelsMenu.init(); + + // don't allow changing of of mixer settings while in a game... + %active = !isObject(ServerConnection); + OP_AudioFrequencyMenu.setActive(%active); + // Changing these audio settings doesn't help Linux performance + if ( $platform $= "linux" ) + { + OP_AudioBitRateMenu.setActive(false); + OP_AudioChannelsMenu.setActive(false); + } + else + { + OP_AudioBitRateMenu.setActive(%active); + OP_AudioChannelsMenu.setActive(%active); + } + + // only allow for disable + if(!%active) + OP_AudioEnvironmentTgl.setActive(%active); + + OP_AudioProviderMenu.setActive(%active); + OP_AudioSpeakerMenu.setActive(%active); + + OP_MasterVolumeSlider.setValue( $pref::Audio::masterVolume ); + OP_EffectsVolumeSlider.setValue( $pref::Audio::effectsVolume ); + OP_VoiceBindVolumeSlider.setValue( $pref::Audio::radioVolume ); + OP_GuiVolumeSlider.setValue( $pref::Audio::guiVolume ); + OP_MusicTgl.onAction(); + OP_MusicVolumeSlider.setValue( $pref::Audio::musicVolume ); + + // Initialize the Voice Settings controls: + OP_MicrophoneEnabledTgl.onAction(); + OP_MicrophoneVolumeSlider.setValue( $pref::Audio::voiceVolume ); + OP_InputBoostSlider.setValue( $pref::Audio::captureGainScale ); + OP_VoiceListenMenu.init(); + OP_VoiceSendMenu.init(); + OP_VoiceCodecInfo.init(); + updateInputBoost(); + + // Initialize the Control Options controls: + OP_ControlGroupMenu.init(); + + if ( isJoystickDetected() ) + { + OP_JoystickTgl.setValue( $pref::Input::JoystickEnabled ); + OP_JoystickTgl.setActive( true ); + OP_ConfigureJoystickBtn.setActive( $pref::Input::JoystickEnabled ); + } + else + { + OP_JoystickTgl.setValue( false ); + OP_JoystickTgl.setActive( false ); + $pref::Input::JoystickEnabled = false; + OP_ConfigureJoystickBtn.setActive( false ); + } + + // Initialize the Network Options controls: + OP_NetworkDisplayHud.init(); + if( !OP_NetworkPresetsMenu.size() ) + OP_NetworkPresetsMenu.init(); + OP_PacketRateSlider.setValue( $pref::Net::PacketRateToClient ); + OP_PacketSizeSlider.setValue( $pref::Net::PacketSize ); + OP_UpdateRateSlider.setValue( $pref::Net::PacketRateToServer ); + if ( !OP_MasterServerMenu.size() ) + OP_MasterServerMenu.init(); + %selId = OP_MasterServerMenu.findText( $pref::Net::DisplayOnMaster ); + if ( %selId == -1 ) + %selId = 1; + OP_MasterServerMenu.setSelected( %selId ); + if ( !OP_RegionMenu.size() ) + OP_RegionMenu.init(); + OP_RegionMenu.setSelected( $pref::Net::RegionMask ); + + // Initialize the Game Options controls: + OP_ZoomSpeedSlider.setValue( 500 - $pref::Player::zoomSpeed ); + OP_LaunchScreenMenu.init(); + + %selId = OP_LaunchScreenMenu.findText( $pref::Shell::LaunchGui ); + if ( %selId == -1 ) + %selId = 1; + OP_LaunchScreenMenu.setText( OP_LaunchScreenMenu.getTextById( %selId ) ); + OP_LaunchScreenMenu.setSelected( %selId ); + + // Hide controls that are not relevant to the demo: + if ( isDemo() ) + { + OP_MasterServerTxt.setVisible( false ); + OP_MasterServerMenu.setVisible( false ); + OP_CheckEmailTgl.setVisible( false ); + OP_ChatDisconnectTgl.setVisible( false ); + OP_EditChatMenuBtn.setVisible( false ); + OP_LaunchScreenTxt.setVisible( false ); + OP_LaunchScreenMenu.setVisible( false ); + } + + %this.setPane( %this.pane ); +} + +//------------------------------------------------------------------------------ +function OptionsDlg::deviceDependent( %this ) +{ + if ( $SwapIntervalSupported ) + { + OP_VSyncTgl.setValue( $pref::Video::disableVerticalSync ); + OP_VSyncTgl.setActive( true ); + } + else + { + OP_VSyncTgl.setValue( false ); + OP_VSyncTgl.setActive( false ); + } + + if ( isDemo() ) + { + OP_TexQualityMenu.setText( "Palletized" ); + OP_TexQualityMenu.setActive( false ); + } + else + { + OP_TexQualityMenu.init(); + if ( $pref::OpenGL::forcePalettedTexture ) + { + $pref::OpenGL::force16bittexture = false; + %selId = 1; + } + else if ( $pref::OpenGL::force16bittexture ) + %selId = 2; + else + %selId = 3; + OP_TexQualityMenu.setSelected( %selId ); + } + + OP_CompressMenu.init(); + if ( $TextureCompressionSupported && !$pref::OpenGL::disableARBTextureCompression ) + { + OP_CompressLabel.setVisible( true ); + OP_CompressLabel_Disabled.setVisible( false ); + OP_CompressMenu.setActive( true ); + if ( !$pref::OpenGL::allowCompression ) + OP_CompressMenu.setSelected( 1 ); + else if ( $pref::OpenGL::compressionHint $= "GL_NICEST" ) + OP_CompressMenu.setSelected( 3 ); + else + OP_CompressMenu.setSelected( 2 ); + } + else + { + OP_CompressLabel_Disabled.setVisible( true ); + OP_CompressLabel.setVisible( false ); + OP_CompressMenu.setActive( false ); + OP_CompressMenu.setText( "None" ); + } + + if ( $FogCoordSupported ) + { + OP_IntTexturedFogTgl.setValue( $pref::Interior::TexturedFog ); + OP_IntTexturedFogTgl.setActive( true ); + } + else + { + OP_IntTexturedFogTgl.setValue( true ); + OP_IntTexturedFogTgl.setActive( false ); + } + + OP_AnisotropySlider.setValue( $pref::OpenGL::anisotropy ); + OP_AnisotropySlider.setActive( $AnisotropySupported ); + if ( $AnisotropySupported ) + { + OP_AnisotropyLabel.setVisible( true ); + OP_AnisotropyLabel_Disabled.setVisible( false ); + } + else + { + OP_AnisotropyLabel_Disabled.setVisible( true ); + OP_AnisotropyLabel.setVisible( false ); + } + + OP_EnvMapTgl.setValue($pref::environmentMaps); + OP_EnvMapTgl.setActive($pref::OpenGL::allowTexGen); +} + +//------------------------------------------------------------------------------ +function OptionsDlg::onSleep( %this ) +{ + OP_VideoDriverMenu.clear(); + OP_ResMenu.clear(); + OP_BPPMenu.clear(); + OP_AudioProviderMenu.clear(); + OP_AudioSpeakerMenu.clear(); + OP_NetworkDisplayHud.uninit(); + + if ( %this.resetAudio ) + { + echo( "Resetting the audio driver..." ); + audioSetDriver( "none" ); + audioSetDriver( $pref::Audio::activeDriver ); + %this.resetAudio = ""; + + // Play the shell hum: (all sources are gone) + if($HudHandle[shellScreen] $= "") + alxStop($HudHandle[shellScreen]); + + $HudHandle[shellScreen] = alxPlay(ShellScreenHumSound, 0, 0, 0); + } + + if ( isObject( ServerConnection ) && isTextureFlushRequired() ) + MessageBoxYesNo( "WARNING", "You have made changes that require Tribes 2 to flush the texture cache. " + @ "Doing this while the game is running can take a long time. " + @ "Do you wish to continue?", + "OptionsDlg.saveSettings();", "returnFromSettings();" ); + else + %this.saveSettings(); +} + +//------------------------------------------------------------------------------ +function isTextureFlushRequired() +{ + if ( $pref::Interior::VertexLighting != OP_VertexLightTgl.getValue() ) + return( true ); + + // We're using the noDrawArraysAlpha variable here because we've already + // gone gold (hard to add a new profiling variable). But the Voodoo2/3/3500 + // cards that have the 256x256 texture limitation (in OpenGL) also have the + // noDrawArraysAlpha hack on...so that works out nice + %mipRange = $pref::OpenGL::noDrawArraysAlpha ? 4 : 5; + if ( $pref::OpenGL::mipReduction != 5 - mFloor( OP_ShapeTexSlider.getValue() * %mipRange ) ) + return( true ); + + if ( $pref::OpenGL::interiorMipReduction != 5 - mFloor( OP_BuildingTexSlider.getValue() * %mipRange ) ) + return( true ); + + if ( $pref::OpenGL::skyMipReduction != 5 - mFloor( OP_SkyTexSlider.getValue() * %mipRange ) ) + return( true ); + + if ( $AnisotropySupported && $pref::OpenGL::anisotropy != OP_AnisotropySlider.getValue() ) + return( true ); + + if ( !isDemo() ) + { + %id = OP_TexQualityMenu.getSelected(); + if ( $pref::OpenGL::forcePalettedTexture ) + { + if ( %id != 1 ) + return( true ); + } + else if ( $pref::OpenGL::force16bittexture ) + { + if ( %id != 2 ) + return( true ); + } + else if ( %id != 3 ) + return( true ); + } + + if ( $TextureCompressionSupported && !$pref::OpenGL::disableARBTextureCompression ) + { + %id = OP_CompressMenu.getSelected(); + if ( $pref::OpenGL::allowCompression ) + { + if ( $pref::OpenGL::compressionHint $= "GL_FASTEST" ) + { + if ( %id != 2 ) + return( true ); + } + else if ( $pref::OpenGL::compressionHint $= "GL_NICEST" ) + { + if ( %id != 3 ) + return( true ); + } + else if ( %id == 1 ) + return( true ); + } + else if ( %id > 1 ) + return( true ); + } + + return( false ); +} + +//------------------------------------------------------------------------------ +function returnFromSettings() +{ + // to unpause singlePlayerGame when returning from options + if ( isObject( Game ) ) + Game.OptionsDlgSleep(); +} + +//------------------------------------------------------------------------------ +function OptionsDlg::saveSettings( %this ) +{ + // Save off any prefs that don't auto-update: + %flushTextures = false; + + if ( $SwapIntervalSupported && OP_VSyncTgl.getValue() != $pref::Video::disableVerticalSync ) + { + $pref::Video::disableVerticalSync = OP_VSyncTgl.getValue(); + setVerticalSync( !$pref::Video::disableVerticalSync ); + } + + %temp = OP_SkyDetailMenu.getSelected(); + if ( %temp == 5 ) + $pref::SkyOn = false; + else + { + $pref::SkyOn = true; + $pref::numCloudLayers = ( 4 - %temp ); + } + + if ( $FogCoordSupported ) + $pref::Interior::TexturedFog = OP_IntTexturedFogTgl.getValue(); + + if ( $pref::Interior::VertexLighting != OP_VertexLightTgl.getValue() ) + { + $pref::Interior::VertexLighting = OP_VertexLightTgl.getValue(); + %flushTextures = true; + } + + %temp = OP_PlayerRenderMenu.getSelected(); + $pref::Player::renderMyPlayer = %temp & 1; + $pref::Player::renderMyItems = %temp & 2; + + if ( !isDemo() ) + { + switch ( OP_TexQualityMenu.getSelected() ) + { + case 1: // 8-bit + if ( !$pref::OpenGL::forcePalettedTexture || $pref::OpenGL::force16bittexture ) + { + $pref::OpenGL::forcePalettedTexture = true; + $pref::OpenGL::force16bittexture = false; + %flushTextures = true; + } + case 2: // 16-bit + if ( $pref::OpenGL::forcePalettedTexture || !$pref::OpenGL::force16bittexture ) + { + $pref::OpenGL::forcePalettedTexture = false; + $pref::OpenGL::force16bittexture = true; + %flushTextures = true; + } + case 3: // 32-bit + if ( $pref::OpenGL::forcePalettedTexture || $pref::OpenGL::force16bittexture ) + { + $pref::OpenGL::forcePalettedTexture = false; + $pref::OpenGL::force16bittexture = false; + %flushTextures = true; + } + } + OP_TexQualityMenu.clear(); + } + + $pref::Terrain::texDetail = 6 - mFloor( OP_TerrainTexSlider.getValue() ); + + // We're using the noDrawArraysAlpha variable here because we've already + // gone gold (hard to add a new profiling variable). But the Voodoo2/3/3500 + // cards that have the 256x256 texture limitation (in OpenGL) also have the + // noDrawArraysAlpha hack on...so that works out nice + %mipRange = $pref::OpenGL::noDrawArraysAlpha ? 4 : 5; + + %temp = 5 - mFloor( OP_ShapeTexSlider.getValue() * %mipRange ); + if ( $pref::OpenGL::mipReduction != %temp ) + { + $pref::OpenGL::mipReduction = %temp; + setOpenGLMipReduction( $pref::OpenGL::mipReduction ); + %flushTextures = true; + } + + %temp = 5 - mFloor( OP_BuildingTexSlider.getValue() * %mipRange ); + if ( $pref::OpenGL::interiorMipReduction != %temp ) + { + $pref::OpenGL::interiorMipReduction = %temp; + setOpenGLInteriorMipReduction( $pref::OpenGL::interiorMipReduction ); + %flushTextures = true; + } + + %temp = 5 - mFloor( OP_SkyTexSlider.getValue() * %mipRange ); + if ( $pref::OpenGL::skyMipReduction != %temp ) + { + $pref::OpenGL::skyMipReduction = %temp; + setOpenGLSkyMipReduction( $pref::OpenGL::skyMipReduction ); + %flushTextures = true; + } + + if ( $TextureCompressionSupported && !$pref::OpenGL::disableARBTextureCompression ) + { + %temp = OP_CompressMenu.getSelected(); + if ( $pref::OpenGL::allowCompression ) + { + switch ( %temp ) + { + case 2: + if ( $pref::OpenGL::compressionHint !$= "GL_FASTEST" ) + { + $pref::OpenGL::compressionHint = "GL_FASTEST"; + setOpenGLTextureCompressionHint( $pref::OpenGL::compressionHint ); + %flushTextures = true; + } + + case 3: + if ( $pref::OpenGL::compressionHint !$= "GL_NICEST" ) + { + $pref::OpenGL::compressionHint = "GL_NICEST"; + setOpenGLTextureCompressionHint( $pref::OpenGL::compressionHint ); + %flushTextures = true; + } + + default: // None + $pref::OpenGL::allowCompression = false; + %flushTextures = true; + } + } + else if ( %temp > 1 ) + { + $pref::OpenGL::allowCompression = true; + if ( %temp == 3 ) + $pref::OpenGL::compressionHint = "GL_NICEST"; + else + $pref::OpenGL::compressionHint = "GL_FASTEST"; + setOpenGLTextureCompressionHint( $pref::OpenGL::compressionHint ); + %flushTextures = true; + } + } + OP_CompressMenu.clear(); + + if ( $AnisotropySupported ) + { + %temp = OP_AnisotropySlider.getValue(); + if ( $pref::OpenGL::anisotropy != %temp ) + { + $pref::OpenGL::anisotropy = %temp; + setOpenGLAnisotropy( $pref::OpenGL::anisotropy ); + %flushTextures = true; + } + } + + if ( !isDemo() ) + { + if ( OP_HiResSkinTgl.getValue() != $pref::use512PlayerSkins ) + { + $pref::use512PlayerSkins = OP_HiResSkinTgl.getValue(); + if ( Canvas.getContent() == GameGui.getId() && GM_WarriorPane.isVisible() ) + GMW_PlayerModel.update(); + } + } + + $pref::Terrain::screenError = $max_screenerror - mFloor( OP_TerrainSlider.getValue() ); + $pref::TS::screenError = $max_TSScreenError - mFloor( OP_ShapeSlider.getValue() * ( $max_TSScreenError - $min_TSScreenError ) ); + $pref::TS::detailAdjust = $min_TSDetailAdjust + OP_ShapeSlider.getValue() * ( $max_TSDetailAdjust - $min_TSDetailAdjust ); + $pref::Shadows = OP_ShadowSlider.getValue(); + $pref::ParticleDensity = 4.0 - OP_ParticleDensitySlider.getValue(); + %val = 100 - OP_DynamicLightSlider.getValue(); + $pref::Interior::DynamicLightsClipPix = $pref::Terrain::DynamicLightsClipPix = %val; + $pref::Interior::DynamicLightsFadePix = $pref::Terrain::DynamicLightsFadePix = 2 * %val; + setShadowDetailLevel( $pref::Shadows ); + $pref::Interior::detailAdjust = OP_InteriorDetailSlider.getValue(); + $pref::VisibleDistanceMod = OP_VisibleDistanceSlider.getValue(); + + $pref::Audio::musicVolume = OP_MusicVolumeSlider.getValue(); + $pref::Audio::masterVolume = OP_MasterVolumeSlider.getValue(); + $pref::Audio::effectsVolume = OP_EffectsVolumeSlider.getValue(); + alxSetChannelVolume( $EffectAudioType, $pref::Audio::effectsVolume ); + $pref::Audio::voiceVolume = OP_MicrophoneVolumeSlider.getValue(); + alxSetChannelVolume( $VoiceAudioType, $pref::Audio::voiceVolume ); + $pref::Audio::radioVolume = OP_VoiceBindVolumeSlider.getValue(); + alxSetChannelVolume( $ChatAudioType, $pref::Audio::radioVolume ); + $pref::Audio::guiVolume = OP_GuiVolumeSlider.getValue(); + alxSetChannelVolume( $GuiAudioType, $pref::Audio::guiVolume); + $pref::Audio::captureGainScale = OP_InputBoostSlider.getValue(); + if ( !$missionRunning ) + MusicPlayer.stop(); + + if ( $pref::Audio::enableVoiceCapture ) + { + %reinit = false; + %selId = OP_VoiceListenMenu.getSelected(); + if ( $pref::Audio::decodingMask != %selId ) + { + $pref::Audio::decodingMask = %selId; + %reinit = true; + } + + %selId = OP_VoiceSendMenu.getSelected(); + if ( $pref::Audio::encodingLevel != %selId ) + { + $pref::Audio::encodingLevel = %selId; + %reinit = true; + } + + if ( %reinit ) + { + alxCaptureDestroy(); + alxCaptureInit(); + + // If in a game, let the server know about the altered settings: + if ( isObject( ServerConnection ) ) + commandToServer( 'SetVoiceInfo', $pref::Audio::voiceChannels, $pref::Audio::decodingMask, $pref::Audio::encodingLevel ); + } + } + + updateNetworkSettings(); + + $pref::Player::zoomSpeed = 500 - mFloor( OP_ZoomSpeedSlider.getValue() ); + setZoomSpeed( $pref::Player::zoomSpeed ); + + $pref::Shell::LaunchGui = OP_LaunchScreenMenu.getText(); + + export( "$pref::*", "prefs/ClientPrefs.cs", false ); + saveActiveMapFile(); + + if ( %flushTextures ) + { + // Give the Options Dialog a chance to go away: + OptionsDlg.schedule( 0, doTextureFlush ); + } + + returnFromSettings(); +} + +//------------------------------------------------------------------------------ +function OptionsDlg::doTextureFlush( %this ) +{ + MessagePopup( "PLEASE WAIT", "Flushing texture cache...\nThis may take a while" ); + Canvas.repaint(); + flushTextureCache(); + CloseMessagePopup(); +} + +//------------------------------------------------------------------------------ +function OptionsDlg::setPane( %this, %pane ) +{ + if((%this.pane $= "Sound") && !$missionRunning) + MusicPlayer.stop(); + + if ( %this.pane !$= "None" ) + { + %paneCtrl = "OP_" @ %this.pane @ "Pane"; + %paneCtrl.setVisible( false ); + + %tabCtrl = "OP_" @ %this.pane @ "Tab"; + %tabCtrl.setValue( false ); + } + + %paneCtrl = "OP_" @ %pane @ "Pane"; + %paneCtrl.setVisible( true ); + + %tabCtrl = "OP_" @ %pane @ "Tab"; + %tabCtrl.setValue( true ); + + %this.pane = %pane; +} + +//------------------------------------------------------------------------------ +function OptionsDlg::applyGraphicChanges( %this ) +{ + %newDriver = OP_VideoDriverMenu.getText(); + %newRes = OP_ResMenu.getText(); + %newBpp = OP_BPPMenu.getText(); + %newFullScreen = OP_FullScreenTgl.getValue(); + + if ( %newDriver !$= $pref::Video::displayDevice ) + { + setDisplayDevice( %newDriver, firstWord( %newRes ), getWord( %newRes, 1 ), %newBpp, %newFullScreen ); + OptionsDlg::deviceDependent( %this ); + } + else + setScreenMode( firstWord( %newRes ), getWord( %newRes, 1 ), %newBpp, %newFullScreen ); + + OP_ApplyBtn.updateState(); +} + + +//------------------------------------------------------------------------------ +function OP_VideoDriverMenu::onSelect( %this, %id, %text ) +{ + // Attempt to keep the same res and bpp settings: + if ( OP_ResMenu.size() > 0 ) + %prevRes = OP_ResMenu.getText(); + else + %prevRes = getWords( $pref::Video::resolution, 0, 1 ); + + // Check if this device is full-screen only: + if ( isDeviceFullScreenOnly( %this.getText() ) ) + { + OP_FullScreenTgl.setValue( true ); + OP_FullScreenTgl.setActive( false ); + OP_FullScreenTgl.onAction(); + } + else + OP_FullScreenTgl.setActive( true ); + + if ( OP_FullScreenTgl.getValue() ) + { + if ( OP_BPPMenu.size() > 0 ) + %prevBPP = OP_BPPMenu.getText(); + else + %prevBPP = getWord( $pref::Video::resolution, 2 ); + } + + // Fill the resolution and bit depth lists: + OP_ResMenu.init( %this.getText(), OP_FullScreenTgl.getValue() ); + OP_BPPMenu.init( %this.getText() ); + + // Try to select the previous settings: + %selId = OP_ResMenu.findText( %prevRes ); + if ( %selId == -1 ) + %selId = 0; + OP_ResMenu.setSelected( %selId ); + + if ( OP_FullScreenTgl.getValue() ) + { + %selId = OP_BPPMenu.findText( %prevBPP ); + if ( %selId == -1 ) + %selId = 0; + OP_BPPMenu.setSelected( %selId ); + OP_BPPMenu.setText( OP_BPPMenu.getTextById( %selId ) ); + } + else + OP_BPPMenu.setText( "Default" ); + + OP_ApplyBtn.updateState(); +} + +//------------------------------------------------------------------------------ +function OP_ResMenu::init( %this, %device, %fullScreen ) +{ + %this.clear(); + %resList = getResolutionList( %device ); + %resCount = getFieldCount( %resList ); + %deskRes = getDesktopResolution(); + %count = 0; + for ( %i = 0; %i < %resCount; %i++ ) + { + %res = getWords( getField( %resList, %i ), 0, 1 ); + + if ( !%fullScreen ) + { + if ( firstWord( %res ) >= firstWord( %deskRes ) ) + continue; + if ( getWord( %res, 1 ) >= getWord( %deskRes, 1 ) ) + continue; + } + + // Only add to list if it isn't there already: + if ( %this.findText( %res ) == -1 ) + { + %this.add( %res, %count ); + %count++; + } + } +} + +//------------------------------------------------------------------------------ +function OP_ResMenu::onSelect( %this, %id, %text ) +{ + OP_ApplyBtn.updateState(); +} + +//------------------------------------------------------------------------------ +function OP_BPPMenu::init( %this, %device ) +{ + %this.clear(); + + if ( %device $= "Voodoo2" ) + %this.add( "16", 0 ); + else + { + %resList = getResolutionList( %device ); + %resCount = getFieldCount( %resList ); + %count = 0; + for ( %i = 0; %i < %resCount; %i++ ) + { + %bpp = getWord( getField( %resList, %i ), 2 ); + + // Only add to list if it isn't there already: + if ( %this.findText( %bpp ) == -1 ) + { + %this.add( %bpp, %count ); + %count++; + } + } + } +} + +//------------------------------------------------------------------------------ +function OP_BPPMenu::onSelect( %this, %id, %text ) +{ + OP_ApplyBtn.updateState(); +} + +//------------------------------------------------------------------------------ +function OP_FullScreenTgl::onAction( %this ) +{ + // Attempt to maintain current settings: + %selId = OP_ResMenu.getSelected(); + if ( %selId == -1 ) + %selId = 0; + %prevRes = OP_ResMenu.getTextById( %selId ); + + OP_ResMenu.init( OP_VideoDriverMenu.getText(), %this.getValue() ); + + %selId = OP_ResMenu.findText( %prevRes ); + if ( %selId == -1 ) + %selId = 0; + OP_ResMenu.setSelected( %selId ); + + if ( %this.getValue() ) + { + %selId = OP_BPPMenu.findText( getWord( $pref::Video::resolution, 2 ) ); + if ( %selId == - 1 ) + %selId = 0; + OP_BPPMenu.setSelected( %selId ); + OP_BPPMenu.setText( OP_BPPMenu.getTextById( %selId ) ); + OP_BPPMenu.setActive( true ); + } + else + { + OP_BPPMenu.setText( "Default" ); + OP_BPPMenu.setActive( false ); + } + + OP_ApplyBtn.updateState(); +} + +//------------------------------------------------------------------------------ +function OP_ApplyBtn::updateState( %this ) +{ + %active = false; + + if ( OP_VideoDriverMenu.getText() !$= $pref::Video::displayDevice ) + %active = true; + else if ( OP_ResMenu.getText() !$= getWords( $pref::Video::resolution, 0, 1 ) ) + %active = true; + else if ( OP_FullScreenTgl.getValue() != $pref::Video::fullScreen ) + %active = true; + else if ( OP_FullScreenTgl.getValue() ) + { + if ( OP_BPPMenu.getText() !$= getWord( $pref::Video::resolution, 2 ) ) + %active = true; + } + + %this.setActive( %active ); +} + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +// Graphics Settings: +// +function updateGammaCorrection() +{ + $pref::OpenGL::gammaCorrection = OP_GammaSlider.getValue(); + videoSetGammaCorrection( $pref::OpenGL::gammaCorrection ); +} + +//------------------------------------------------------------------------------ +function updateTerrainDetail() +{ + $pref::Terrain::screenError = $max_screenerror - mFloor( OP_TerrainSlider.getValue()); + if ( OP_TerrainSlider.getValue() != $max_screenerror - $pref::Terrain::screenError ) + OP_TerrainSlider.setValue( $max_screenerror - $pref::Terrain::screenError ); +} + +//------------------------------------------------------------------------------ +function updateDynamicLightSliderState() +{ + %on = $pref::Interior::DynamicLights || $pref::Terrain::dynamicLights; + OP_DynamicLightText.setVisible( %on ); + OP_DynamicLightText_Disabled.setVisible( !%on ); + OP_DynamicLightSlider.setActive( %on ); +} + +//------------------------------------------------------------------------------ +function OP_SkyDetailMenu::init( %this ) +{ + %this.clear(); + %this.add( "Full Sky", 1 ); + %this.add( "Two Cloud Layers", 2 ); + %this.add( "One Cloud Layer", 3 ); + %this.add( "Sky Box Only", 4 ); + %this.add( "No Sky", 5 ); +} + +//------------------------------------------------------------------------------ +function OP_PlayerRenderMenu::init( %this ) +{ + %this.clear(); + %this.add( "Player and Items", 3 ); + %this.add( "Player only", 1 ); + %this.add( "Items only", 2 ); + %this.add( "Neither Player nor Items", 0 ); +} + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +// Texture Settings: +// +function OP_CompressMenu::init( %this ) +{ + %this.clear(); + %this.add( "None", 1 ); + %this.add( "Fastest", 2 ); + %this.add( "Nicest", 3 ); +} + +//------------------------------------------------------------------------------ +function OP_TexQualityMenu::init( %this ) +{ + %this.clear(); + if ( $PalettedTextureSupported ) + %this.add( "Palletized", 1 ); + %this.add( "16 bit", 2 ); + %this.add( "32 bit", 3 ); +} + +//------------------------------------------------------------------------------ +function OP_TexQualityMenu::onSelect( %this, %id, %text ) +{ + if ( %id == 1 ) + { + // Disable these with palletized textures by default: + OP_EnvMapTgl.setValue( false ); + //OP_EnvMapTgl.setActive( false ); + OP_IntEnvMapTgl.setValue( false ); + //OP_IntEnvMapTgl.setActive( false ); + } +// else +// { +// OP_EnvMapTgl.setActive( true ); +// OP_IntEnvMapTgl.setActive( true ); +// } +} + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +// Audio Settings: +// +function setAudioProvider(%idx) +{ + alxContexti(ALC_PROVIDER, %idx); + $pref::Audio::provider = alxGetContextstr(ALC_PROVIDER_NAME, %idx); + + %active = audioIsEnvironmentProvider($pref::Audio::provider); + + // unset tgl if cannot be environment provider + if(!%active) + OP_AudioEnvironmentTgl.setValue(false); + OP_AudioEnvironmentTgl.setActive(%active); + + audioUpdateProvider($pref::Audio::provider); + OP_AudioProviderMenu.setSelected(%idx); +} + +//------------------------------------------------------------------------------ +function OP_AudioEnvironmentTgl::onAction(%this) +{ + alxEnableEnvironmental(%this.getValue()); +} + +//------------------------------------------------------------------------------ +function OP_AudioProviderMenu::onSelect(%this, %id, %text) +{ + if(%id != $Audio::originalProvider) + { + if(!%this.seenWarning) + { + MessageBoxOK("Warning", "Changing sound drivers may result in incompatibilities and game oddities. If you experience such oddities, hit \"Reset\" to restore defaults.", ""); + %this.seenWarning = true; + } + OP_AudioResetProvider.setActive(true); + } + setAudioProvider(%id); +} + +//------------------------------------------------------------------------------ +function OP_AudioResetProvider::onAction(%this) +{ + setAudioProvider($Audio::originalProvider); + %this.setActive(false); +} +//------------------------------------------------------------------------------ +function OP_AudioSpeakerMenu::onSelect(%this, %id, %text) +{ + alxContexti(ALC_SPEAKER, %id); + $pref::Audio::speakerType = alxGetContextstr(ALC_SPEAKER_NAME, %id); +} + +//------------------------------------------------------------------------------ +function OP_AudioFrequencyMenu::init( %this ) +{ + %this.clear(); + %this.add( "11 KHz", 0 ); + %this.add( "22 KHz", 1 ); + %this.add( "44 KHz", 2 ); + + switch ( $pref::Audio::frequency ) + { + case 11025: %this.setSelected( 0 ); + case 22050: %this.setSelected( 1 ); + default: %this.setSelected( 2 ); + } +} + +//------------------------------------------------------------------------------ +function OP_AudioFrequencyMenu::onSelect( %this, %id, %text ) +{ + switch ( %id ) + { + case 0: %newVal = 11025; + case 1: %newVal = 22050; + default: %newVal = 44100; + } + + if ( $pref::Audio::frequency != %newVal ) + { + $pref::Audio::frequency = %newVal; + OptionsDlg.resetAudio = true; + } +} + +//------------------------------------------------------------------------------ +function OP_AudioBitRateMenu::init( %this ) +{ + %this.clear(); + %this.add( "8 bit", 0 ); + %this.add( "16 bit", 1 ); + + if ( $pref::Audio::sampleBits == 8 ) + %this.setSelected( 0 ); + else + %this.setSelected( 1 ); +} + +//------------------------------------------------------------------------------ +function OP_AudioBitRateMenu::onSelect( %this, %id, %text ) +{ + %newVal = %id == 0 ? 8 : 16; + if ( $pref::Audio::sampleBits != %newVal ) + { + $pref::Audio::sampleBits = %newVal; + OptionsDlg.resetAudio = true; + } +} + +//------------------------------------------------------------------------------ +function OP_AudioChannelsMenu::init( %this ) +{ + %this.clear(); + %this.add( "One", 0 ); + %this.add( "Two", 1 ); + + if ( $pref::Audio::channels == 1 ) + %this.setSelected( 0 ); + else + %this.setSelected( 1 ); +} + +//------------------------------------------------------------------------------ +function OP_AudioChannelsMenu::onSelect( %this, %id, %text ) +{ + %newVal = %id == 0 ? 1 : 2; + if ( $pref::Audio::channels != %newVal ) + { + $pref::Audio::channels = %newVal; + OptionsDlg.resetAudio = true; + } +} + +//------------------------------------------------------------------------------ +function OP_MusicTgl::onAction( %this ) +{ + %on = %this.getValue(); + OP_MusicVolumeLabel.setVisible( %on ); + OP_MusicVolumeLabel_Disabled.setVisible( !%on ); + OP_MusicVolumeSlider.setActive( %on ); + $pref::Audio::musicEnabled = %on; + + if ( %on ) + MusicPlayer.play(); + else + MusicPlayer.stop(); +} + +//------------------------------------------------------------------------------ +function updateMusicVolume() +{ + %volume = OP_MusicVolumeSlider.getValue(); + alxSetChannelVolume( $MusicAudioType, %volume ); +} + +//------------------------------------------------------------------------------ +function updateGuiVolume() +{ + %volume = OP_GuiVolumeSlider.getValue(); + alxSetChannelVolume( $GuiAudioType, %volume ); +} + +//------------------------------------------------------------------------------ +function updateMasterVolume() +{ + %volume = OP_MasterVolumeSlider.getValue(); + alxListenerf( AL_GAIN_LINEAR, %volume ); +} + + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +// Voice Settings: +// +function OP_MicrophoneEnabledTgl::onAction( %this ) +{ + %on = %this.getValue(); + OP_RecordTestBtn.setActive( %on ); + OP_MicVolumeLabel.setVisible( %on ); + OP_MicVolumeLabel_Disabled.setVisible( !%on ); + OP_MicrophoneVolumeSlider.setActive( %on ); + OP_InputBoostLabel.setVisible( %on ); + OP_InputBoostLabel_Disabled.setVisible( !%on ); + OP_InputBoostSlider.setActive( %on ); + OP_InputBoostPercentTxt.setVisible( %on ); + OP_VoiceListenLabel.setVisible( %on ); + OP_VoiceListenLabel_Disabled.setVisible( !%on ); + OP_VoiceListenMenu.setActive( %on ); + OP_VoiceSendLabel.setVisible( %on ); + OP_VoiceSendLabel_Disabled.setVisible( !%on ); + OP_VoiceSendMenu.setActive( %on ); + + if(%on != alxIsEnabled("capture")) + { + if(%on) + alxCaptureInit(); + else + alxCaptureDestroy(); + } +} + +//------------------------------------------------------------------------------ +function updateInputBoost() +{ + %val = OP_InputBoostSlider.getValue(); + alxSetCaptureGainScale( %val ); + %val = mFloor(%val * 100); + OP_InputBoostPercentTxt.setValue(%val @ "%"); +} + +//------------------------------------------------------------------------------ +function OP_RecordTestBtn::onAction( %this ) +{ + alxCaptureStart(true); +} + +//------------------------------------------------------------------------------ +function localCaptureStart( %method ) +{ + if(%method $= "record") + { + OP_RecordTestBtn.setActive(false); + OP_RecordTestBtn.setValue(">> Recording <<"); + } + else + { + OP_RecordTestBtn.setActive(false); + OP_RecordTestBtn.setValue(">> Playing <<"); + } +} + +//------------------------------------------------------------------------------ +function localCaptureStop( %method ) +{ + if(%method $= "play") + { + OP_RecordTestBtn.setActive(true); + OP_RecordTestBtn.setValue("Test Record"); + } +} + +//------------------------------------------------------------------------------ +function OP_VoiceListenMenu::init( %this ) +{ + %this.clear(); + %this.add( "", 0 ); + if ( $platform !$= "linux" ) { + %this.add( ".v12", 1 ); + %this.add( ".v12 - .v24", 3 ); + %this.add( ".v12 - .v29", 7 ); + } + if ( $platform $= "linux" ) { + %this.add( "GSM" , 8 ); + } + + switch ( $pref::Audio::decodingMask ) + { + case 0 or 3 or 7 or 8: + %this.setSelected( $pref::Audio::decodingMask ); + default: + %this.setSelected( 1 ); + } +} + +//------------------------------------------------------------------------------ +function OP_VoiceSendMenu::init( %this ) +{ + %this.clear(); + if ( $platform !$= "linux" ) { + %this.add( ".v12", 0 ); + %this.add( ".v24", 1 ); + %this.add( ".v29", 2 ); + } + if ( $platform $= "linux" ) { + %this.add( "GSM", 3 ); + } + + %this.setSelected($pref::Audio::encodingLevel); +} + +function OP_VoiceCodecInfo::init( %this ) +{ + %headerStyle = ""; + if ( $platform $= "linux" ) { + %displayText = "" @ %headerStyle @ "Voice Codec Information:" NL + "\n" @ + " GSM: fixed bitrate codec (6.6 kbits/sec linux only)" NL + "\n" @ + "" @ + "Setting your codec levels too high can have adverse" @ + " affects on network performance." @ + ""; + } else { + %displayText = "" @ %headerStyle @ "Voice Codec Information:" NL + "\n" @ + " .v12: variable bitrate codec (~1.2 kbits/sec win only)" NL + " .v24: fixed bitrate codec (2.4 kbits/sec win only)" NL + " .v29: fixed bitrate codec (2.9 kbits/sec win only)" NL + "\n" @ + "" @ + "Setting your codec levels too high can have adverse" @ + " affects on network performance." @ + ""; + } + + %this.setText(%displayText); + %this.setActive(false); +} + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +// Driver Info dialog: +// +function DriverInfoDlg::onWake( %this ) +{ + %headerStyle = ""; + %infoString = getVideoDriverInfo(); + %displayText = "" @ %headerStyle @ "VENDOR:" NL + " " @ getField( %infoString, 0 ) NL + "" @ %headerStyle @ "RENDERER:" NL + " " @ getField( %infoString, 1 ) NL + "" @ %headerStyle @ "VERSION " @ getField( %infoString, 2 ) NL + "\n" @ + "" @ %headerStyle @ "SUPPORTED OPENGL EXTENSIONS:" NL + getField( %infoString, 3 ); + + DriverInfoText.setText( %displayText ); +} + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +// Control remapper section: +// +$RemapCount = 0; +$RemapName[$RemapCount] = "Forward"; +$RemapCmd[$RemapCount] = "moveforward"; +$RemapCount++; +$RemapName[$RemapCount] = "Backward"; +$RemapCmd[$RemapCount] = "movebackward"; +$RemapCount++; +$RemapName[$RemapCount] = "Strafe Left"; +$RemapCmd[$RemapCount] = "moveleft"; +$RemapCount++; +$RemapName[$RemapCount] = "Strafe Right"; +$RemapCmd[$RemapCount] = "moveright"; +$RemapCount++; +$RemapName[$RemapCount] = "Turn Left"; +$RemapCmd[$RemapCount] = "turnLeft"; +$RemapCount++; +$RemapName[$RemapCount] = "Turn Right"; +$RemapCmd[$RemapCount] = "turnRight"; +$RemapCount++; +$RemapName[$RemapCount] = "Look Up"; +$RemapCmd[$RemapCount] = "panUp"; +$RemapCount++; +$RemapName[$RemapCount] = "Look Down"; +$RemapCmd[$RemapCount] = "panDown"; +$RemapCount++; +$RemapName[$RemapCount] = "Jump"; +$RemapCmd[$RemapCount] = "jump"; +$RemapCount++; +$RemapName[$RemapCount] = "Jet Pack"; +$RemapCmd[$RemapCount] = "mouseJet"; +$RemapCount++; +$RemapName[$RemapCount] = "Fire Weapon"; +$RemapCmd[$RemapCount] = "mouseFire"; +$RemapCount++; +$RemapName[$RemapCount] = "Zoom"; +$RemapCmd[$RemapCount] = "toggleZoom"; +$RemapCount++; +$RemapName[$RemapCount] = "Cycle Zoom Level"; +$RemapCmd[$RemapCount] = "setZoomFOV"; +$RemapCount++; +$RemapName[$RemapCount] = "Weapon Slot One"; +$RemapCmd[$RemapCount] = "useFirstWeaponSlot"; +$RemapCount++; +$RemapName[$RemapCount] = "Weapon Slot Two"; +$RemapCmd[$RemapCount] = "useSecondWeaponSlot"; +$RemapCount++; +$RemapName[$RemapCount] = "Weapon Slot Three"; +$RemapCmd[$RemapCount] = "useThirdWeaponSlot"; +$RemapCount++; +$RemapName[$RemapCount] = "Weapon Slot Four"; +$RemapCmd[$RemapCount] = "useFourthWeaponSlot"; +$RemapCount++; +$RemapName[$RemapCount] = "Weapon Slot Five"; +$RemapCmd[$RemapCount] = "useFifthWeaponSlot"; +$RemapCount++; +$RemapName[$RemapCount] = "Weapon Slot Six"; +$RemapCmd[$RemapCount] = "useSixthWeaponSlot"; +$RemapCount++; +$RemapName[$RemapCount] = "Blaster"; +$RemapCmd[$RemapCount] = "useBlaster"; +$RemapCount++; +$RemapName[$RemapCount] = "Plasma Rifle"; +$RemapCmd[$RemapCount] = "usePlasma"; +$RemapCount++; +$RemapName[$RemapCount] = "Chaingun"; +$RemapCmd[$RemapCount] = "useChaingun"; +$RemapCount++; +$RemapName[$RemapCount] = "Spinfusor"; +$RemapCmd[$RemapCount] = "useDisc"; +$RemapCount++; +$RemapName[$RemapCount] = "Grenade Launcher"; +$RemapCmd[$RemapCount] = "useGrenadeLauncher"; +$RemapCount++; +$RemapName[$RemapCount] = "Laser Rifle"; +$RemapCmd[$RemapCount] = "useSniperRifle"; +$RemapCount++; +$RemapName[$RemapCount] = "ELF Projector"; +$RemapCmd[$RemapCount] = "useELFGun"; +$RemapCount++; +$RemapName[$RemapCount] = "Fusion Mortar"; +$RemapCmd[$RemapCount] = "useMortar"; +$RemapCount++; +$RemapName[$RemapCount] = "Missile Launcher"; +$RemapCmd[$RemapCount] = "useMissileLauncher"; +$RemapCount++; +$RemapName[$RemapCount] = "Shocklance"; +$RemapCmd[$RemapCount] = "useShockLance"; +$RemapCount++; +$RemapName[$RemapCount] = "Targeting Laser"; +$RemapCmd[$RemapCount] = "useTargetingLaser"; +$RemapCount++; +$RemapName[$RemapCount] = "Previous Weapon"; +$RemapCmd[$RemapCount] = "prevWeapon"; +$RemapCount++; +$RemapName[$RemapCount] = "Next Weapon"; +$RemapCmd[$RemapCount] = "nextWeapon"; +$RemapCount++; +$RemapName[$RemapCount] = "Throw Grenade"; +$RemapCmd[$RemapCount] = "throwGrenade"; +$RemapCount++; +$RemapName[$RemapCount] = "Place Mine"; +$RemapCmd[$RemapCount] = "placeMine"; +$RemapCount++; +$RemapName[$RemapCount] = "Use Pack"; +$RemapCmd[$RemapCount] = "useBackpack"; +$RemapCount++; +$RemapName[$RemapCount] = "Use Health Kit"; +$RemapCmd[$RemapCount] = "useRepairKit"; +$RemapCount++; +$RemapName[$RemapCount] = "Deploy Beacon"; +$RemapCmd[$RemapCount] = "placeBeacon"; +$RemapCount++; +$RemapName[$RemapCount] = "Inventory"; +$RemapCmd[$RemapCount] = "toggleInventoryHud"; +$RemapCount++; +$RemapName[$RemapCount] = "Favorite 1"; +$RemapCmd[$RemapCount] = "selectFavorite1"; +$RemapCount++; +$RemapName[$RemapCount] = "Favorite 2"; +$RemapCmd[$RemapCount] = "selectFavorite2"; +$RemapCount++; +$RemapName[$RemapCount] = "Favorite 3"; +$RemapCmd[$RemapCount] = "selectFavorite3"; +$RemapCount++; +$RemapName[$RemapCount] = "Favorite 4"; +$RemapCmd[$RemapCount] = "selectFavorite4"; +$RemapCount++; +$RemapName[$RemapCount] = "Favorite 5"; +$RemapCmd[$RemapCount] = "selectFavorite5"; +$RemapCount++; +$RemapName[$RemapCount] = "Favorite 6"; +$RemapCmd[$RemapCount] = "selectFavorite6"; +$RemapCount++; +$RemapName[$RemapCount] = "Favorite 7"; +$RemapCmd[$RemapCount] = "selectFavorite7"; +$RemapCount++; +$RemapName[$RemapCount] = "Favorite 8"; +$RemapCmd[$RemapCount] = "selectFavorite8"; +$RemapCount++; +$RemapName[$RemapCount] = "Favorite 9"; +$RemapCmd[$RemapCount] = "selectFavorite9"; +$RemapCount++; +$RemapName[$RemapCount] = "Favorite 10"; +$RemapCmd[$RemapCount] = "selectFavorite10"; +$RemapCount++; +$RemapName[$RemapCount] = "Favorite 11"; +$RemapCmd[$RemapCount] = "selectFavorite11"; +$RemapCount++; +$RemapName[$RemapCount] = "Favorite 12"; +$RemapCmd[$RemapCount] = "selectFavorite12"; +$RemapCount++; +$RemapName[$RemapCount] = "Favorite 13"; +$RemapCmd[$RemapCount] = "selectFavorite13"; +$RemapCount++; +$RemapName[$RemapCount] = "Favorite 14"; +$RemapCmd[$RemapCount] = "selectFavorite14"; +$RemapCount++; +$RemapName[$RemapCount] = "Favorite 15"; +$RemapCmd[$RemapCount] = "selectFavorite15"; +$RemapCount++; +$RemapName[$RemapCount] = "Favorite 16"; +$RemapCmd[$RemapCount] = "selectFavorite16"; +$RemapCount++; +$RemapName[$RemapCount] = "Favorite 17"; +$RemapCmd[$RemapCount] = "selectFavorite17"; +$RemapCount++; +$RemapName[$RemapCount] = "Favorite 18"; +$RemapCmd[$RemapCount] = "selectFavorite18"; +$RemapCount++; +$RemapName[$RemapCount] = "Favorite 19"; +$RemapCmd[$RemapCount] = "selectFavorite19"; +$RemapCount++; +$RemapName[$RemapCount] = "Favorite 20"; +$RemapCmd[$RemapCount] = "selectFavorite20"; +$RemapCount++; +$RemapName[$RemapCount] = "Select Energy Pack"; +$RemapCmd[$RemapCount] = "quickPackEnergyPack"; +$RemapCount++; +$RemapName[$RemapCount] = "Select Repair Pack"; +$RemapCmd[$RemapCount] = "quickPackRepairPack"; +$RemapCount++; +$RemapName[$RemapCount] = "Select Shield Pack"; +$RemapCmd[$RemapCount] = "quickPackShieldPack"; +$RemapCount++; +$RemapName[$RemapCount] = "Select Cloaking Pack"; +$RemapCmd[$RemapCount] = "quickPackCloakPack"; +$RemapCount++; +$RemapName[$RemapCount] = "Select Sensor Jammer"; +$RemapCmd[$RemapCount] = "quickPackJammerPack"; +$RemapCount++; +$RemapName[$RemapCount] = "Select Ammo Pack"; +$RemapCmd[$RemapCount] = "quickPackAmmoPack"; +$RemapCount++; +$RemapName[$RemapCount] = "Select Satchel Charge"; +$RemapCmd[$RemapCount] = "quickPackSatchelCharge"; +$RemapCount++; +$RemapName[$RemapCount] = "Select Inv Station"; +$RemapCmd[$RemapCount] = "quickPackDeployableStation"; +$RemapCount++; +$RemapName[$RemapCount] = "Select Spider Turret"; +$RemapCmd[$RemapCount] = "quickPackIndoorTurret"; +$RemapCount++; +$RemapName[$RemapCount] = "Select Landspike Turret"; +$RemapCmd[$RemapCount] = "quickPackOutdoorTurret"; +$RemapCount++; +$RemapName[$RemapCount] = "Select Motion Sensor"; +$RemapCmd[$RemapCount] = "quickPackMotionSensor"; +$RemapCount++; +$RemapName[$RemapCount] = "Select Deploy Pulse"; +$RemapCmd[$RemapCount] = "quickPackPulse"; +$RemapCount++; +$RemapName[$RemapCount] = "Select Plasma Barrel"; +$RemapCmd[$RemapCount] = "quickPackPlasmaBarrel"; +$RemapCount++; +$RemapName[$RemapCount] = "Select Missile Barrel"; +$RemapCmd[$RemapCount] = "quickPackMissileBarrel"; +$RemapCount++; +$RemapName[$RemapCount] = "Select AA Barrel"; +$RemapCmd[$RemapCount] = "quickPackAABarrel"; +$RemapCount++; +$RemapName[$RemapCount] = "Select Mortar Barrel"; +$RemapCmd[$RemapCount] = "quickPackMortarBarrel"; +$RemapCount++; +$RemapName[$RemapCount] = "Select Elf Barrel"; +$RemapCmd[$RemapCount] = "quickPackElfBarrel"; +$RemapCount++; +$RemapName[$RemapCount] = "Select Grenade"; +$RemapCmd[$RemapCount] = "quickPackGrenade"; +$RemapCount++; +$RemapName[$RemapCount] = "Select Flash Grenade"; +$RemapCmd[$RemapCount] = "quickPackFlashGrenade"; +$RemapCount++; +$RemapName[$RemapCount] = "Select Concussion"; +$RemapCmd[$RemapCount] = "quickPackConcussionGrenade"; +$RemapCount++; +$RemapName[$RemapCount] = "Select Camera"; +$RemapCmd[$RemapCount] = "quickPackCameraGrenade"; +$RemapCount++; +$RemapName[$RemapCount] = "Select Flare Grenade"; +$RemapCmd[$RemapCount] = "quickPackFlareGrenade"; +$RemapCount++; +$RemapName[$RemapCount] = "Command Circuit"; +$RemapCmd[$RemapCount] = "toggleCommanderMap"; +$RemapCount++; +$RemapName[$RemapCount] = "Toggle Task List"; +$RemapCmd[$RemapCount] = "toggleTaskListDlg"; +$RemapCount++; +$RemapName[$RemapCount] = "Accept Task"; +$RemapCmd[$RemapCount] = "fnAcceptTask"; +$RemapCount++; +$RemapName[$RemapCount] = "Decline Task"; +$RemapCmd[$RemapCount] = "fnDeclineTask"; +$RemapCount++; +$RemapName[$RemapCount] = "Task Completed"; +$RemapCmd[$RemapCount] = "fnTaskCompleted"; +$RemapCount++; +$RemapName[$RemapCount] = "Reset Task List"; +$RemapCmd[$RemapCount] = "fnResetTaskList"; +$RemapCount++; +$RemapName[$RemapCount] = "Vote Yes"; +$RemapCmd[$RemapCount] = "voteYes"; +$RemapCount++; +$RemapName[$RemapCount] = "Vote No"; +$RemapCmd[$RemapCount] = "voteNo"; +$RemapCount++; +$RemapName[$RemapCount] = "Voice Chat Menu"; +$RemapCmd[$RemapCount] = "activateChatMenuHud"; +$RemapCount++; +$RemapName[$RemapCount] = "Global Chat"; +$RemapCmd[$RemapCount] = "ToggleMessageHud"; +$RemapCount++; +$RemapName[$RemapCount] = "Team Chat"; +$RemapCmd[$RemapCount] = "TeamMessageHud"; +$RemapCount++; +$RemapName[$RemapCount] = "Resize Chat Hud"; +$RemapCmd[$RemapCount] = "resizeChatHud"; +$RemapCount++; +$RemapName[$RemapCount] = "Toggle Microphone"; +$RemapCmd[$RemapCount] = "voiceCapture"; +$RemapCount++; +$RemapName[$RemapCount] = "Toggle Help Text"; +$RemapCmd[$RemapCount] = "toggleHelpGui"; +$RemapCount++; +$RemapName[$RemapCount] = "Score Screen"; +$RemapCmd[$RemapCount] = "toggleScoreScreen"; +$RemapCount++; +$RemapName[$RemapCount] = "Free Look"; +$RemapCmd[$RemapCount] = "toggleFreeLook"; +$RemapCount++; +$RemapName[$RemapCount] = "Exterior View"; +$RemapCmd[$RemapCount] = "toggleFirstPerson"; +$RemapCount++; +$RemapName[$RemapCount] = "Drop Weapon"; +$RemapCmd[$RemapCount] = "throwWeapon"; +$RemapCount++; +$RemapName[$RemapCount] = "Drop Pack"; +$RemapCmd[$RemapCount] = "throwPack"; +$RemapCount++; +$RemapName[$RemapCount] = "Drop Flag"; +$RemapCmd[$RemapCount] = "throwFlag"; +$RemapCount++; +$RemapName[$RemapCount] = "Suicide"; +$RemapCmd[$RemapCount] = "suicide"; +$RemapCount++; +$RemapName[$RemapCount] = "Toggle Personal Wypts"; +$RemapCmd[$RemapCount] = "toggleHudWaypoints"; +$RemapCount++; +$RemapName[$RemapCount] = "Toggle Mission Wypts"; +$RemapCmd[$RemapCount] = "toggleHudMarkers"; +$RemapCount++; +$RemapName[$RemapCount] = "Toggle Beacons"; +$RemapCmd[$RemapCount] = "toggleHudTargets"; +$RemapCount++; +$RemapName[$RemapCount] = "Toggle Commands"; +$RemapCmd[$RemapCount] = "toggleHudCommands"; +$RemapCount++; +$RemapName[$RemapCount] = "Construction Tool"; +$RemapCmd[$RemapCount] = "useConstructionTool"; +$RemapCount++; + +// Construction +$RemapName[$RemapCount] = "Select Light Support Beam"; +$RemapCmd[$RemapCount] = "quickPackLightSupportBeam"; +$RemapCount++; +$RemapName[$RemapCount] = "Select Light Walkway"; +$RemapCmd[$RemapCount] = "quickPackLightWalkway"; +$RemapCount++; +$RemapName[$RemapCount] = "Select Light Blast Wall"; +$RemapCmd[$RemapCount] = "quickPackLightBlastWall"; +$RemapCount++; +$RemapName[$RemapCount] = "Select Medium Support Beam"; +$RemapCmd[$RemapCount] = "quickPackMediumSupportBeam"; +$RemapCount++; +$RemapName[$RemapCount] = "Select Medium Floor"; +$RemapCmd[$RemapCount] = "quickPackMediumFloor"; +$RemapCount++; +//$RemapName[$RemapCount] = "Select Disc Turret"; +//$RemapCmd[$RemapCount] = "quickPackDiscTurret"; +//$RemapCount++; +$RemapName[$RemapCount] = "Select Large Inventory Station"; +$RemapCmd[$RemapCount] = "quickPackLargeInventoryStation"; +$RemapCount++; +$RemapName[$RemapCount] = "Select Generator Pack"; +$RemapCmd[$RemapCount] = "quickPackGeneratorPack"; +$RemapCount++; +$RemapName[$RemapCount] = "Select Solar Panel Pack"; +$RemapCmd[$RemapCount] = "quickPackSolarPanelPack"; +$RemapCount++; +$RemapName[$RemapCount] = "Select Switch Pack"; +$RemapCmd[$RemapCount] = "quickPackSwitchPack"; +$RemapCount++; +$RemapName[$RemapCount] = "Select Medium Sensor Pack"; +$RemapCmd[$RemapCount] = "quickPackMediumSensorPack"; +$RemapCount++; +$RemapName[$RemapCount] = "Select Large Sensor Pack"; +$RemapCmd[$RemapCount] = "quickPackLargeSensorPack"; +$RemapCount++; +$RemapName[$RemapCount] = "Select Teleport Pad"; +$RemapCmd[$RemapCount] = "quickPackTeleportPad"; +$RemapCount++; +$RemapName[$RemapCount] = "Select Deployable Turret Base"; +$RemapCmd[$RemapCount] = "quickPackDeployableTurretBase"; +$RemapCount++; +$RemapName[$RemapCount] = "Select Energizer"; +$RemapCmd[$RemapCount] = "quickPackEnergizer"; +$RemapCount++; +$RemapName[$RemapCount] = "Select Tree Pack"; +$RemapCmd[$RemapCount] = "quickPackTreePack"; +$RemapCount++; +$RemapName[$RemapCount] = "Select Crate Pack"; +$RemapCmd[$RemapCount] = "quickPackCratePack"; +$RemapCount++; +$RemapName[$RemapCount] = "Select Decoration Pack"; +$RemapCmd[$RemapCount] = "quickPackDecorationPack"; +$RemapCount++; +$RemapName[$RemapCount] = "Select Light Pack"; +$RemapCmd[$RemapCount] = "quickPackLightPack"; +$RemapCount++; +$RemapName[$RemapCount] = "Select Tripwire Pack"; +$RemapCmd[$RemapCount] = "quickPackTripwirePack"; +$RemapCount++; +$RemapName[$RemapCount] = "Select Logo Projector Pack"; +$RemapCmd[$RemapCount] = "quickPackLogoProjectorPack"; +$RemapCount++; +//$RemapName[$RemapCount] = "Select Laser Turret"; +//$RemapCmd[$RemapCount] = "quickPackLaserTurret"; +//$RemapCount++; +$RemapName[$RemapCount] = "Select Missile Rack Turret"; +$RemapCmd[$RemapCount] = "quickPackMissileRackTurret"; +$RemapCount++; +$RemapName[$RemapCount] = "Select Force Field"; +$RemapCmd[$RemapCount] = "quickPackForceField"; +$RemapCount++; +$RemapName[$RemapCount] = "Select Gravity Field"; +$RemapCmd[$RemapCount] = "quickPackGravityField"; +$RemapCount++; +$RemapName[$RemapCount] = "Select Jump Pad"; +$RemapCmd[$RemapCount] = "quickPackJumpPad"; +$RemapCount++; +$RemapName[$RemapCount] = "Select Escape Pod"; +$RemapCmd[$RemapCount] = "quickPackEscapePod"; +$RemapCount++; +$RemapName[$RemapCount] = "Pack Setting: Fwd"; +$RemapCmd[$RemapCount] = "cyclePackFwd"; +$RemapCount++; +$RemapName[$RemapCount] = "Pack Setting: Back"; +$RemapCmd[$RemapCount] = "cyclePackBack"; +$RemapCount++; +$RemapName[$RemapCount] = "Pack Setting: FFwd"; +$RemapCmd[$RemapCount] = "cyclePackFFwd"; +$RemapCount++; +$RemapName[$RemapCount] = "Pack Setting: FBack"; +$RemapCmd[$RemapCount] = "cyclePackFBack"; +$RemapCount++; +$RemapName[$RemapCount] = "Emote: Sit Down"; +$RemapCmd[$RemapCount] = "emoteSitDown"; +$RemapCount++; +$RemapName[$RemapCount] = "Emote: Squat"; +$RemapCmd[$RemapCount] = "emoteSquat"; +$RemapCount++; +$RemapName[$RemapCount] = "Emote: Jig"; +$RemapCmd[$RemapCount] = "emoteJig"; +$RemapCount++; +$RemapName[$RemapCount] = "Emote: Lie Down"; +$RemapCmd[$RemapCount] = "emoteLieDown"; +$RemapCount++; +$RemapName[$RemapCount] = "Emote: Heart Attack"; +$RemapCmd[$RemapCount] = "emoteHeartAttack"; +$RemapCount++; +$RemapName[$RemapCount] = "Emote: Sucker Punched"; +$RemapCmd[$RemapCount] = "emoteSuckerPunched"; +$RemapCount++; +$quickPackExtrasBind = true; +// End Construction + +if ( !isDemo() ) +{ + $RemapName[$RemapCount] = "Start Demo Record"; + $RemapCmd[$RemapCount] = "startRecordingDemo"; + $RemapCount++; + $RemapName[$RemapCount] = "Stop Demo Record"; + $RemapCmd[$RemapCount] = "stopRecordingDemo"; + $RemapCount++; +} +$RemapName[$RemapCount] = "Chat Page Up"; +$RemapCmd[$RemapCount] = "pageMessageHudUp"; +$RemapCount++; +$RemapName[$RemapCount] = "Chat Page Down"; +$RemapCmd[$RemapCount] = "pageMessageHudDown"; +$RemapCount++; +$RemapName[$RemapCount] = "Toggle Net Meter"; +$RemapCmd[$RemapCount] = "toggleNetDisplayHud"; +$RemapCount++; + +$ObsRemapCount = 0; +$ObsRemapName[$ObsRemapCount] = "Move Up"; +$ObsRemapCmd[$ObsRemapCount] = "moveup"; +$ObsRemapCount++; +$ObsRemapName[$ObsRemapCount] = "Move Down"; +$ObsRemapCmd[$ObsRemapCount] = "movedown"; +$ObsRemapCount++; +$ObsRemapName[$ObsRemapCount] = "Toggle Observer Mode"; +$ObsRemapCmd[$ObsRemapCount] = "jump"; +$ObsRemapCount++; +$ObsRemapName[$ObsRemapCount] = "Spawn/Previous"; +$ObsRemapCmd[$ObsRemapCount] = "mouseFire"; +$ObsRemapCount++; +$ObsRemapName[$ObsRemapCount] = "Cycle Camera/Next"; +$ObsRemapCmd[$ObsRemapCount] = "mouseJet"; +$ObsRemapCount++; + +//------------------------------------------------------------------------------ +function restoreDefaultMappings() +{ + moveMap.delete(); + exec( "scripts/controlDefaults.cs" ); + $pref::Input::ActiveConfig = "MyConfig"; + OP_RemapList.fillList(); +} + +//------------------------------------------------------------------------------ +function isMapFile( %file ) +{ + %fObject = new FileObject(); + if ( !%fObject.openForRead( %file ) ) + return( false ); + + while ( !%fObject.isEOF() ) + { + %line = %fObject.readLine(); + if ( %line $= "// Tribes 2 Input Map File" ) + { + %fObject.close(); + return( true ); + } + } + + %fObject.close(); + return( false ); +} + +//------------------------------------------------------------------------------ +function isValidMapFileSaveName( %file ) +{ + if (isDemo()) + %basePath = "demo_base/"; + else + %basePath = "base/"; + if ( !isWriteableFileName( %basePath @ %file ) ) + return( false ); + + if ( isFile( %file ) ) + return( isMapFile( %file ) ); + + return( true ); +} + +//------------------------------------------------------------------------------ +function loadMapFile( %filename ) +{ + exec( "prefs/" @ %filename @ ".cs" ); + $pref::Input::ActiveConfig = %filename; + OP_RemapList.fillList(); +} + +//------------------------------------------------------------------------------ +function saveActiveMapFile() +{ + if ( isValidMapFileSaveName( "prefs/" @ $pref::Input::ActiveConfig @ ".cs" ) ) + saveMapFile( $pref::Input::ActiveConfig ); + else + ShellGetSaveFilename( "SAVE CONTROL CONFIG", "prefs/*.cs", "isMapFile", "saveMapFile", "" ); +} + +//------------------------------------------------------------------------------ +function saveMapFile( %filename ) +{ + if ( strcspn( %filename, "\\/?*\"\'<>|" ) < strlen( %filename ) ) + { + MessageBoxOK( "SAVE FAILED", "Filenames may not contain any of the following characters:" NL "\\ / ? * < > \" \' |", + "ShellGetSaveFilename( \"SAVE CONTROL CONFIG\", \"prefs/*.cs\", \"isMapFile\", \"saveMapFile\", $pref::Input::ActiveConfig );" ); + return; + } + + if (isDemo()) + %basePath = "demo_base/"; + else + %basePath = "base/"; + %mapFile = "prefs/" @ %filename @ ".cs"; + if ( !isWriteableFileName( %basePath @ %mapFile ) ) + { + MessageBoxOK( "SAVE FAILED", "That is not a writeable file name. Please choose another file name.", + "ShellGetSaveFilename( \"SAVE CONTROL CONFIG\", \"prefs/*.cs\", \"isMapFile\", \"saveMapFile\", $pref::Input::ActiveConfig );" ); + return; + } + + if ( isFile( %mapFile ) && !isMapFile( %mapFile ) ) + { + MessageBoxOK( "SAVE FAILED", "A file of that name already exists and is not an input configuration file. Please choose another file name.", + "ShellGetSaveFilename( \"SAVE CONTROL CONFIG\", \"prefs/*.cs\", \"isMapFile\", \"saveMapFile\", $pref::Input::ActiveConfig );" ); + return; + } + + moveMap.save( %mapFile ); + // Append the observer action map: + observerMap.save( %mapFile, true ); + + // Write out the console toggle key: + %fObject = new FileObject(); + if ( %fObject.openForAppend( %mapFile ) ) + { + %bind = GlobalActionMap.getBinding( "toggleConsole" ); + if ( %bind !$= "" ) + { + %fObject.writeLine( "GlobalActionMap.bind(keyboard, \"" @ getField( %bind, 1 ) @ "\", toggleConsole);" ); + %fObject.close(); + } + } + %fObject.delete(); + + $pref::Input::ActiveConfig = %filename; +} + +//------------------------------------------------------------------------------ +function getMapDisplayName( %device, %action ) +{ + if ( %device $= "keyboard" ) + return( %action ); + else if ( strstr( %device, "mouse" ) != -1 ) + { + // Substitute "mouse" for "button" in the action string: + %pos = strstr( %action, "button" ); + if ( %pos != -1 ) + { + %mods = getSubStr( %action, 0, %pos ); + %object = getSubStr( %action, %pos, 1000 ); + %instance = getSubStr( %object, strlen( "button" ), 1000 ); + return( %mods @ "mouse" @ ( %instance + 1 ) ); + } + else + error( "Mouse input object other than button passed to getDisplayMapName!" ); + } + else if ( strstr( %device, "joystick" ) != -1 ) + { + // Substitute "joystick" for "button" in the action string: + %pos = strstr( %action, "button" ); + if ( %pos != -1 ) + { + %mods = getSubStr( %action, 0, %pos ); + %object = getSubStr( %action, %pos, 1000 ); + %instance = getSubStr( %object, strlen( "button" ), 1000 ); + return( %mods @ "joystick" @ ( %instance + 1 ) ); + } + else + { + %pos = strstr( %action, "pov" ); + if ( %pos != -1 ) + { + %wordCount = getWordCount( %action ); + %mods = %wordCount > 1 ? getWords( %action, 0, %wordCount - 2 ) @ " " : ""; + %object = getWord( %action, %wordCount - 1 ); + switch$ ( %object ) + { + case "upov": %object = "POV1 up"; + case "dpov": %object = "POV1 down"; + case "lpov": %object = "POV1 left"; + case "rpov": %object = "POV1 right"; + case "upov2": %object = "POV2 up"; + case "dpov2": %object = "POV2 down"; + case "lpov2": %object = "POV2 left"; + case "rpov2": %object = "POV2 right"; + default: %object = "??"; + } + return( %mods @ %object ); + } + else + error( "Unsupported Joystick input object passed to getDisplayMapName!" ); + } + } + + return( "??" ); +} + +//------------------------------------------------------------------------------ +function buildFullMapString( %index ) +{ + switch$ ( OP_ControlsPane.group ) + { + case "Observer": + %actionMap = observerMap; + %name = $ObsRemapName[%index]; + %cmd = $ObsRemapCmd[%index]; + + default: + %actionMap = moveMap; + %name = $RemapName[%index]; + %cmd = $RemapCmd[%index]; + } + + %temp = %actionMap.getBinding( %cmd ); + %device = getField( %temp, 0 ); + %object = getField( %temp, 1 ); + if ( %device !$= "" && %object !$= "" ) + %mapString = getMapDisplayName( %device, %object ); + else + %mapString = ""; + + return( %name TAB %mapString ); +} + +//------------------------------------------------------------------------------ +function OP_ControlGroupMenu::init( %this ) +{ + %selId = %this.getSelected(); + %this.clear(); + %this.add( "Main", 0 ); + %this.add( "Observer", 1 ); + %this.setSelected( %selId ); + %this.onSelect( %selId, %this.getTextById( %selId ) ); +} + +//------------------------------------------------------------------------------ +function OP_ControlGroupMenu::onSelect( %this, %id, %text ) +{ + OP_ControlsPane.group = %text; + OP_RemapList.fillList(); +} + +//------------------------------------------------------------------------------ +function OP_RemapList::fillList( %this ) +{ + switch$ ( OP_ControlsPane.group ) + { + case "Observer": %count = $ObsRemapCount; + default: %count = $RemapCount; + } + + %this.clear(); + for ( %i = 0; %i < %count; %i++ ) + %this.addRow( %i, buildFullMapString( %i ) ); + + // Set the console key: + %bind = GlobalActionMap.getBinding( "toggleConsole" ); + OP_ConsoleKeyBtn.setValue( getField( %bind, 1 ) ); +} + +//------------------------------------------------------------------------------ +function OP_RemapList::onDeleteKey( %this, %rowId ) +{ + switch$ ( OP_ControlsPane.group ) + { + case "Observer": + %actionMap = observerMap; + %cmd = $ObsRemapCmd[%rowId]; + default: + %actionMap = moveMap; + %cmd = $RemapCmd[%rowId]; + } + clearMapping( %actionMap, %cmd ); + %this.setRowById( %rowId, buildFullMapString( %rowId ) ); +} + +//------------------------------------------------------------------------------ +function OP_RemapList::doRemap( %this ) +{ + %selId = %this.getSelectedId(); + switch$ ( OP_ControlsPane.group ) + { + case "Observer": %name = $ObsRemapName[%selId]; + default: %name = $RemapName[%selId]; + } + + RemapFrame.setTitle( "REMAP \"" @ %name @ "\"" ); + RemapInputCtrl.mode = "move"; + RemapInputCtrl.index = %selId; + Canvas.pushDialog( RemapDlg ); +} + +//------------------------------------------------------------------------------ +function OP_ConsoleKeyBtn::doRemap( %this ) +{ + RemapFrame.setTitle( "REMAP \"Toggle Console\"" ); + RemapInputCtrl.mode = "consoleKey"; + RemapInputCtrl.index = 0; + Canvas.pushDialog( RemapDlg ); +} + +//------------------------------------------------------------------------------ +function RemapDlg::onWake( %this ) +{ + $enableDirectInput = "1"; + activateDirectInput(); + + if ( RemapInputCtrl.mode $= "consoleKey" ) + RemapText.setText( "Press a key to assign it to this action" NL "or Esc to cancel..." ); + else + RemapText.setText( "Press a key or button to assign it to this action" NL "or Esc to cancel..." ); +} + +//------------------------------------------------------------------------------ +function RemapDlg::onSleep( %this ) +{ + $enableDirectInput = "1"; + deactivateDirectInput(); +} + +//------------------------------------------------------------------------------ +function findRemapCmdIndex( %command ) +{ + switch$ ( OP_ControlsPane.group ) + { + case "Observer": + for ( %i = 0; %i < $ObsRemapCount; %i++ ) + { + if ( %command $= $ObsRemapCmd[%i] ) + return( %i ); + } + default: + for ( %i = 0; %i < $RemapCount; %i++ ) + { + if ( %command $= $RemapCmd[%i] ) + return( %i ); + } + } + + return( -1 ); +} + +//------------------------------------------------------------------------------ +function clearMapping( %actionMap, %cmd ) +{ + %fullMapString = %actionMap.getBinding( %cmd ); + %mapCount = getRecordCount( %fullMapString ); + for ( %i = 0; %i < %mapCount; %i++ ) + { + %temp = getRecord( %fullMapString, %i ); + %actionMap.unbind( getField( %temp, 0 ), getField( %temp, 1 ) ); + } +} + +//------------------------------------------------------------------------------ +function redoMapping( %actionMap, %device, %action, %cmd, %oldIndex, %newIndex ) +{ + //%actionMap.bind( %device, %action, $RemapCmd[%newIndex] ); + %actionMap.bind( %device, %action, %cmd ); + OP_RemapList.setRowById( %oldIndex, buildFullMapString( %oldIndex ) ); + OP_RemapList.setRowById( %newIndex, buildFullMapString( %newIndex ) ); +} + +//------------------------------------------------------------------------------ +function redoConsoleMapping( %action, %oldIndex ) +{ + moveMap.unbind( "keyboard", %action ); + GlobalActionMap.bind( "keyboard", %action, "toggleConsole" ); + OP_ConsoleKeyBtn.setValue( %action ); + OP_RemapList.setRowById( %oldIndex, buildFullMapString( %oldIndex ) ); +} + +//------------------------------------------------------------------------------ +function RemapInputCtrl::onInputEvent( %this, %device, %action ) +{ + //error( "** onInputEvent called - device = " @ %device @ ", action = " @ %action @ " **" ); + Canvas.popDialog( RemapDlg ); + + // Test for the reserved keystrokes: + if ( %device $= "keyboard" ) + { + // Cancel... + if ( %action $= "escape" ) + { + // Do nothing... + return; + } + } + + if ( %this.mode $= "consoleKey" ) + { + if ( %device !$= "keyboard" ) + { + MessageBoxOK( "REMAP FAILED", "This command can only be bound to keys on the keyboard!" ); + return; + } + + %prevMap = GlobalActionMap.getCommand( %device, %action ); + if ( %prevMap !$= "" ) + { + MessageBoxOK( "REMAP FAILED", "\"" @ getMapDisplayName( %device, %action ) @ "\" is already bound to a non-remappable command!" ); + return; + } + + %mvMap = moveMap.getCommand( %device, %action ); + if ( %mvMap $= "" ) + { + GlobalActionMap.bind( %device, %action, "toggleConsole" ); + OP_ConsoleKeyBtn.setValue( %action ); + } + else + { + %mapName = getMapDisplayName( %device, %action ); + %mvMapIndex = findRemapCmdIndex( %mvMap ); + if ( %mvMapIndex == -1 ) + MessageBoxOK( "REMAP FAILED", "\"" @ %mapName @ "\" is already bound to a non-remappable command!" ); + else + MessageBoxYesNo( "WARNING", "\"" @ %mapName @ "\" is already bound to \"" + @ $RemapName[%mvMapIndex] @ "\"!" + NL "Do you want to undo this mapping?", + "redoConsoleMapping(\"" @ %action @ "\", " @ %mvMapIndex @ ");", "" ); + return; + } + } + else + { + switch$ ( OP_ControlsPane.group ) + { + case "Observer": + %actionMap = observerMap; + %cmd = $ObsRemapCmd[%this.index]; + %name = $ObsRemapName[%this.index]; + + default: + %actionMap = moveMap; + %cmd = $RemapCmd[%this.index]; + %name = $RemapName[%this.index]; + } + + // First check to see if the given action is already mapped: + %prevMap = %actionMap.getCommand( %device, %action ); + if ( %prevMap !$= %cmd ) + { + if ( %prevMap $= "" ) + { + %actionMap.bind( %device, %action, %cmd ); + OP_RemapList.setRowById( %this.index, buildFullMapString( %this.index ) ); + } + else + { + %mapName = getMapDisplayName( %device, %action ); + %prevMapIndex = findRemapCmdIndex( %prevMap ); + if ( %prevMapIndex == -1 ) + MessageBoxOK( "REMAP FAILED", "\"" @ %mapName @ "\" is already bound to a non-remappable command!" ); + else + { + switch$ ( OP_ControlsPane.group ) + { + case "Observer": + %prevCmdName = $ObsRemapName[%prevMapIndex]; + default: + %prevCmdName = $RemapName[%prevMapIndex]; + } + + MessageBoxYesNo( "WARNING", + "\"" @ %mapName @ "\" is already bound to \"" + @ %prevCmdName @ "\"!\nDo you want to undo this mapping?", + "redoMapping(" @ %actionMap @ ", " @ %device @ ", \"" @ %action @ "\", \"" @ %cmd @ "\", " @ %prevMapIndex @ ", " @ %this.index @ ");", "" ); + } + return; + } + } + } +} + +//------------------------------------------------------------------------------ +function OP_JoystickTgl::onAction( %this ) +{ + %on = %this.getValue(); + if ( %on ) + enableJoystick(); + else + disableJoystick(); + + OP_ConfigureJoystickBtn.setActive( %on ); +} + +//------------------------------------------------------------------------------ +function MouseConfigDlg::onWake( %this ) +{ + MouseXSlider.setValue( moveMap.getScale( mouse, xaxis ) / 2 ); + MouseYSlider.setValue( moveMap.getScale( mouse, yaxis ) / 2 ); + InvertMouseTgl.setValue( moveMap.isInverted( mouse, yaxis ) ); + + MouseZActionMenu.clear(); + MouseZActionMenu.add( "Nothing", 1 ); + MouseZActionMenu.add( "Cycle Weapon", 2 ); + MouseZActionMenu.add( "Next Weapon Only", 3 ); +// MouseZActionMenu.add( "Cycle Zoom Level", 4 ); + + %bind = moveMap.getCommand( "mouse", "zaxis" ); + %selId = 1; + switch$ ( %bind ) + { + case "cycleWeaponAxis": + %selId = 2; + case "cycleNextWeaponOnly": + %selId = 3; + } + MouseZActionMenu.setSelected( %selId ); +} + +//------------------------------------------------------------------------------ +function MouseConfigDlg::onOK( %this ) +{ + %xSens = MouseXSlider.getValue() * 2; + %ySens = MouseYSlider.getValue() * 2; + moveMap.bind( mouse, xaxis, "S", %xSens, "yaw" ); + %yFlags = InvertMouseTgl.getValue() ? "SI" : "S"; + moveMap.bind( mouse, yaxis, %yFlags, %ySens, "pitch" ); + + switch ( MouseZActionMenu.getSelected() ) + { + case 2: + moveMap.bind( mouse, zaxis, cycleWeaponAxis ); + case 3: + moveMap.bind( mouse, zaxis, cycleNextWeaponOnly ); + default: + moveMap.unbind( mouse, zaxis ); + } + + Canvas.popDialog( MouseConfigDlg ); +} + +//------------------------------------------------------------------------------ +function MouseXSlider::sync( %this ) +{ + %thisValue = %this.getValue(); + MouseXText.setValue( "(" @ getSubStr( %thisValue, 0, 4 ) @ ")" ); + if ( $pref::Input::LinkMouseSensitivity ) + { + if ( MouseYSlider.getValue() != %thisValue ) + MouseYSlider.setValue( %thisValue ); + } +} + +//------------------------------------------------------------------------------ +function MouseYSlider::sync( %this ) +{ + %thisValue = %this.getValue(); + MouseYText.setValue( "(" @ getSubStr( %thisValue, 0, 4 ) @ ")" ); + if ( $pref::Input::LinkMouseSensitivity ) + { + if ( MouseXSlider.getValue() != %thisValue ) + MouseXSlider.setValue( %thisValue ); + } +} + +//------------------------------------------------------------------------------ +// Joystick Config dialog: +//------------------------------------------------------------------------------ +$JoyRemapCount = 0; +$JoyRemapName[$JoyRemapCount] = "Look Up/Down"; +$JoyRemapCmd[$JoyRemapCount] = "joyPitch"; +$JoyRemapCount++; +$JoyRemapName[$JoyRemapCount] = "Turn Left/Right"; +$JoyRemapCmd[$JoyRemapCount] = "joyYaw"; +$JoyRemapCount++; +$JoyRemapName[$JoyRemapCount] = "Move Forward/Backward"; +$JoyRemapCmd[$JoyRemapCount] = "joystickMoveY"; +$JoyRemapCount++; +$JoyRemapName[$JoyRemapCount] = "Strafe Left/Right"; +$JoyRemapCmd[$JoyRemapCount] = "joystickMoveX"; +$JoyRemapCount++; +$JoyRemapName[$JoyRemapCount] = "Cycle Weapon"; +$JoyRemapCmd[$JoyRemapCount] = "cycleWeaponAxis"; +$JoyRemapCount++; + +//------------------------------------------------------------------------------ +function JoystickConfigDlg::onWake( %this ) +{ + // Add all of the axis tabs: + %temp = getJoystickAxes( 0 ); + %tryCount = getField( %temp, 0 ); + $JoyAxisCount = 0; + + for ( %i = 0; %i < %tryCount; %i++ ) + { + %type = getField( %temp, %i + 1 ); + switch$ ( %type ) + { + case "X": %tabName = "X Axis"; %tabType = "xaxis"; + case "Y": %tabName = "Y Axis"; %tabType = "yaxis"; + case "Z": %tabName = "Z Axis"; %tabType = "zaxis"; + case "R": %tabName = "R Axis"; %tabType = "rxaxis"; + case "U": %tabName = "U Axis"; %tabType = "ryaxis"; + case "V": %tabName = "V Axis"; %tabType = "rzaxis"; + case "S": %tabName = "Slider"; %tabType = "slider"; + case "L": %tabName = "Slider 2"; %tabType = "slider2"; + default: %tabName = ""; + } + + if ( %tabName !$= "" ) + { + $JoyAxisTab[$JoyAxisCount] = new ShellTabButton() { + profile = "ShellTabProfile"; + horizSizing = "right"; + vertSizing = "bottom"; + position = "29" SPC ( 52 + ( %i * 30 ) ); + extent = "100 38"; + minExtent = "48 38"; + visible = "1"; + command = "JoystickConfigDlg.setPane(" @ %i @ ");"; + helpTag = "0"; + text = %tabName; + type = %tabType; + }; + + $JoyAxisCount++; + JoystickConfigFrame.add( $JoyAxisTab[%i] ); + } + } + + // Fill the action menu: + JoyAxisActionMenu.clear(); + for ( %i = 0; %i < $JoyRemapCount; %i++ ) + JoyAxisActionMenu.add( $JoyRemapName[%i], %i ); + JoyAxisActionMenu.add( "Nothing", 255 ); + + // Select the first axis: + %this.setPane( %this.pane ); +} + +//------------------------------------------------------------------------------ +function JoystickConfigDlg::onSleep( %this ) +{ + // Save the current pane's settings: + bindJoystickAxis( %this.pane, JoyAxisActionMenu.getSelected() ); + for ( %i = 0; %i < $JoyAxisCount; %i++ ) + { + JoystickConfigFrame.remove( $JoyAxisTab[%i] ); + $JoyAxisTab[%i].delete(); + } +} + +//------------------------------------------------------------------------------ +function JoystickConfigDlg::setPane( %this, %pane ) +{ + if ( %this.pane != %pane ) + { + // Save the previous axes' settings: + bindJoystickAxis( %this.pane, JoyAxisActionMenu.getSelected() ); + %this.pane = %pane; + } + + for ( %i = 0; %i < $joyAxisCount; %i++ ) + $JoyAxisTab[%i].setValue( %i == %pane ); + + // Update the config controls: + %axisType = $JoyAxisTab[%pane].type; + %bind = moveMap.getCommand( "joystick", %axisType ); + if ( %bind !$= "" ) + { + for ( %i = 0; %i < $JoyRemapCount; %i++ ) + { + if ( $JoyRemapCmd[%i] $= %bind ) + { + JoyAxisActionMenu.setSelected( %i ); + JoyAxisActionMenu.setText( $JoyRemapName[%i] ); + JoyAxisActionMenu.onSelect( %i, "" ); + break; + } + } + + if ( %i == $JoyRemapCount ) + { + JoyAxisActionMenu.setSelected( 255 ); // 255 is the code for "Nothing" + JoyAxisActionMenu.onSelect( 255, "" ); + } + + %scale = moveMap.getScale( "joystick", %axisType ); + JoyAxisSlider.setValue( %scale / 100 ); + %deadZone = moveMap.getDeadZone( "joystick", %axisType ); + if ( %deadZone $= "0 0" ) + DeadZoneSlider.setValue( 0.0 ); + else + DeadZoneSlider.setValue( abs( firstWord( %deadZone ) ) / %scale ); + InvertJoyAxisTgl.setValue( moveMap.isInverted( "joystick", %axisType ) ); + //JoyAxisRelativeTgl.setValue( moveMap.isRelativeAxis( "joystick", %axisType ) ); + } + else + { + JoyAxisActionMenu.setSelected( 255 ); // 255 is the code for "Nothing" + JoyAxisActionMenu.onSelect( 255, "" ); + JoyAxisSlider.setValue( 0.5 ); + DeadZoneSlider.setValue( 0.0 ); + InvertJoyAxisTgl.setValue( false ); + //JoyAxisRelativeTgl.setValue( %axisType $= "slider" ); + } +} + +//------------------------------------------------------------------------------ +function JoyAxisActionMenu::onSelect( %this, %id, %text ) +{ + %on = ( %id < $JoyRemapCount ); + JoyAxisSlider.setActive( %on ); + JoySensText.setVisible( %on ); + DeadZoneSlider.setActive( %on ); + DeadZoneText.setVisible( %on ); + InvertJoyAxisTgl.setActive( %on ); + //JoyAxisRelativeTgl.setActive( %on ); +} + +//------------------------------------------------------------------------------ +function JoySensText::update( %this ) +{ + %this.setValue( "(" @ getSubStr( JoyAxisSlider.getValue(), 0, 4 ) @ ")" ); +} + +//------------------------------------------------------------------------------ +function DeadZoneText::update( %this ) +{ + %val = DeadZoneSlider.getValue(); + %percent = %val * 100; + %temp = strstr( %percent, "." ); + if ( %temp != -1 ) + %percent = getSubStr( %percent, 0, %temp ); + + %this.setValue( "(" @ %percent @ "%)" ); +} + +//------------------------------------------------------------------------------ +function bindJoystickAxis( %axisIndex, %cmdIndex ) +{ + %cmd = $JoyRemapCmd[%cmdIndex]; + %axis = $JoyAxisTab[%axisIndex].type; + if ( %cmdIndex > $JoyRemapCount ) + { + // Make sure the axis is unbound: + moveMap.unbind( "joystick", %axis ); + return; + } + + %sens = JoyAxisSlider.getValue() * 100; + %delta = DeadZoneSlider.getValue() * %sens; + %flags = "S"; + if ( InvertJoyAxisTgl.getValue() ) + %flags = %flags @ "I"; +// if ( JoyAxisRelativeTgl.getValue() ) +// %flags = %flags @ "L"; + if ( %delta > 0 ) + { + %deadZone = "-" @ %delta SPC %delta; + moveMap.bind( "joystick", %axis, %flags @ "D", %deadZone, %sens, %cmd ); + } + else + moveMap.bind( "joystick", %axis, %flags, %sens, %cmd ); +} + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +// Network Settings: +// + +function updateNetworkSettings() +{ + $pref::Net::PacketRateToClient = mFloor( OP_PacketRateSlider.getValue() ); + $pref::Net::PacketSize = mFloor( OP_PacketSizeSlider.getValue() ); + $pref::Net::PacketRateToServer = mFloor( OP_UpdateRateSlider.getValue() ); + + // check the max rate: + if ( isObject( ServerConnection ) ) + ServerConnection.checkMaxRate(); + if ( isObject( ClientGroup ) ) + { + %count = ClientGroup.getCount(); + for ( %i = 0; %i < %count; %i++ ) + { + %cl = ClientGroup.getObject( %i ); + %cl.checkMaxRate(); + } + } +} + +function OP_NetworkDisplayHud::init(%this) +{ + %this.getPrefs(); + + %this.textHeight = 14; + %this.textOffset = 2; + + if(!%this.infoCallback) + { + %this.textProfile = 0; + return; + } + + // profile for the text fields + %this.textProfile = new GuiControlProfile() + { + fontType = $ShellButtonFont; + fontSize = $ShellButtonFontSize; + autoSizeWidth = true; + autoSizeHeight = true; + fontColors[6] = "128 128 128"; + }; + + %yOffset = %this.textOffset; + + for(%i = 0; %i < 6; %i++) + { + // set the text color + %this.textProfile.fontColors[%i] = %this.fieldColors[%i]; + + // create the text field + %this.textField[%i] = new GuiTextCtrl() + { + profile = %this.textProfile; + horizSizing = "right"; + vertSizing = "bottom"; + position = "20 " @ %yOffset; + extent = "190 " @ %this.textHeight; + visible = "1"; + }; + + // create the toggle field + %this.toggleField[%i] = new GuiTextCtrl() + { + profile = ShellActiveTextProfile; + horizSizing = "right"; + vertSizing = "bottom"; + position = "5 " @ %yOffset; + extent = "15 " @ %this.textHeight; + visible = "1"; + }; + + // create a mouse object + %this.mouseField[%i] = new GuiMouseEventCtrl(NetworkDisplayMouseCtrl) + { + profile = GuiDefaultProfile; + horizSizing = "right"; + vertSizing = "bottom"; + position = "10 " @ %yOffset; + extent = "200 " @ %this.textHeight; + visible = "1"; + fieldIndex = %i; + }; + + OP_NetworkDisplayTextFrame.add(%this.textField[%i]); + OP_NetworkDisplayTextFrame.add(%this.toggleField[%i]); + OP_NetworkDisplayTextFrame.add(%this.mouseField[%i]); + + %yOffset += (%this.textHeight + %this.textOffset); + } + %this.infoUpdate(0, 0, 0, 0, 0, 0); +} + +function NetworkDisplayMouseCtrl::onMouseDown(%this) +{ + %b = OP_NetworkDisplayHud.renderField[%this.fieldIndex]; + OP_NetworkDisplayHud.renderField[%this.fieldIndex] = !%b; + OP_NetworkDisplayHud.updateToggles(); +} + +function OP_NetworkDisplayHud::uninit(%this) +{ + if(!%this.infoCallback) + return; + + if(isObject(%this.textProfile)) + %this.textProfile.delete(); + + for(%i = 0; %i < 6; %i++) + { + if(isObject(%this.textField[%i])) + %this.textField[%i].delete(); + + if(isObject(%this.toggleField[%i])) + %this.toggleField[%i].delete(); + + if(isObject(%this.mouseField[%i])) + %this.mouseField[%i].delete(); + } +} + +function OP_NetworkDisplayHud::updateToggles(%this) +{ + // update the toggles + $pref::Net::graphFields = 0; + + for(%i = 0; %i < 6; %i++) + { + $pref::Net::graphFields |= %this.renderField[%i] << %i; + %this.toggleField[%i].setText(%this.renderField[%i] ? "+" : "-"); + } +} + +function OP_NetworkDisplayHud::infoUpdate(%this, %ping, %packetLoss, %sendPackets, %sendBytes, %receivePackets, %receiveBytes) +{ + %this.updateToggles(); + + // set the text + %this.textField[0].setText("\c0Ping: " @ mFormatFloat(%ping, "%4.0f") @ "ms"); + %this.textField[1].setText("\c1Packet Loss: " @ mFormatFloat(%packetLoss, "%3.0f") @ "%"); + %this.textField[2].setText("\c2Send Packets: " @ mFormatFloat(%sendPackets, "%2.1f") @ "pps"); + %this.textField[3].setText("\c3Send Bytes: " @ mFormatFloat(%sendBytes, "%5.0f") @ "bps"); + %this.textField[4].setText("\c4Receive Packets: " @ mFormatFloat(%receivePackets, "%2.1f") @ "pps"); + %this.textField[5].setText("\c5Receive Bytes: " @ mFormatFloat(%receiveBytes, "%5.0f") @ "bps"); +} + +// "" +// [1,32] [8,32] [100,450] +$NetworkPresetCount = 0; +$NetworkPreset[$NetworkPresetCount] = "28.8 Modem\t12\t16\t200"; $NetworkPresetCount++; +$NetworkPreset[$NetworkPresetCount] = "56K Modem\t16\t20\t240"; $NetworkPresetCount++; +$NetworkPreset[$NetworkPresetCount] = "DSL\t20\t24\t350"; $NetworkPresetCount++; +$NetworkPreset[$NetworkPresetCount] = "Cable\t24\t24\t400"; $NetworkPresetCount++; +$NetworkPreset[$NetworkPresetCount] = "T1/LAN\t32\t32\t450"; $NetworkPresetCount++; + +function OP_NetworkPresetsMenu::init( %this ) +{ + %this.clear(); + for(%i = 0; %i < $NetworkPresetCount; %i++) + %this.add( getField($NetworkPreset[%i], 0), %i); + + // don't update settings on init (only update when values change) + %this.updateSettings = false; + %this.setSelected($pref::Net::Preset); + %this.updateSettings = true; +} + +function OP_NetworkPresetsMenu::onSelect( %this, %id, %text ) +{ + OP_PacketRateSlider.setValue( getField($NetworkPreset[%id], 1) ); + OP_UpdateRateSlider.setValue( getField($NetworkPreset[%id], 2) ); + OP_PacketSizeSlider.setValue( getField($NetworkPreset[%id], 3) ); + + if(%this.updateSettings) + updateNetworkSettings(); + $pref::Net::Preset = %id; +} + +//------------------------------------------------------------------------------ +function OP_MasterServerMenu::init( %this ) +{ + %this.clear(); + // You can change these strings, but NOT THE IDS! + %this.add( "Always", 1 ); + %this.add( "When Not Full", 2 ); + %this.add( "Never", 3 ); +} + +//------------------------------------------------------------------------------ +function OP_MasterServerMenu::onSelect( %this, %id, %text ) +{ + switch( %id ) + { + case 2: + $pref::Net::DisplayOnMaster = "NotFull"; + case 3: + $pref::Net::DisplayOnMaster = "Never"; + default: + $pref::Net::DisplayOnMaster = "Always"; + } +} + +//------------------------------------------------------------------------------ +function OP_RegionMenu::init( %this ) +{ + %this.clear(); + %this.add( "North America East", 1 ); + %this.add( "North America West", 2 ); + %this.add( "South America", 4 ); + %this.add( "Australia", 8 ); + %this.add( "Asia", 16 ); + %this.add( "Europe", 32 ); +} + +//------------------------------------------------------------------------------ +function OP_RegionMenu::onSelect( %this, %id, %text ) +{ + $pref::Net::RegionMask = %id; +} + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +// Game Settings: +// +function OP_LaunchScreenMenu::init( %this ) +{ + %this.clear(); + %this.add( "Game", 1 ); + %this.add( "Email", 4 ); + %this.add( "Chat", 5 ); + %this.add( "Browser", 6 ); +} + +//------------------------------------------------------------------------------ +function toggleInvertYAxis() +{ + // Catch the case where this is toggled in-game while in a vehicle: + if ( isObject( passengerKeys ) ) + { + %bind = passengerKeys.getBinding( pitch ); + if ( %bind !$= "" ) + { + %device = getField( %bind, 0 ); + %action = getField( %bind, 1 ); + %flags = $pref::Vehicle::InvertYAxis ? "SDI" : "SD"; + %deadZone = passengerKeys.getDeadZone( %device, %action ); + %scale = passengerKeys.getScale( %device, %action ); + passengerKeys.bind( %device, %action, %flags, %deadZone, %scale, pitch ); + } + } +} + +//------------------------------------------------------------------------------ +function toggleImmersion() +{ + MessageBoxOK( "Force Feedback", "This will take effect the next time you start Tribes 2." ); +} + +//------------------------------------------------------------------------------ +function toggleVehicleTeleportPref() +{ + // If we are in a game, let the server know we've changed; + if ( isObject( ServerConnection ) ) + commandToServer( 'EnableVehicleTeleport', $pref::Vehicle::pilotTeleport ); +} diff --git a/scripts/TR2Game.cs b/scripts/TR2Game.cs new file mode 100644 index 0000000..16cb716 --- /dev/null +++ b/scripts/TR2Game.cs @@ -0,0 +1,31 @@ +// Bastardized for Contruction Mod to load the player datablocks +// without screwing up the rest of the game. + +// DisplayName = Team Rabbit 2 + +//--- GAME RULES BEGIN --- +//Get the flag and throw it into the other team's goal +//You can only hold onto the flag for 15 seconds +//Passing the flag increases the size of the Jackpot +//Scoring a goal awards the Jackpot to your team! +//When your health reaches zero, you are knocked down +//Replenish your ammo by pressing your suicide button +//--- GAME RULES END --- + + + +// Team Rabbit 2 +// Created by Codality, Inc. +// www.codality.com +// ------------------------------- +// Michael "KineticPoet" Johnston - Designer, Lead Programmer, Maps +// Dan "daunt" Kolta - Physics design, Maps +// Scott "FSB-AO" Estabrook - Programmer +// John "CObbler" Carter - Bonus sound effects +// Buddy "sLaM" Pritchard - Sound effects +// Gregg "illy" Fellows - 3D models and skins +// Alan "Nefilim" Schwertel; - Maps +// Kenneth "SONOFMAN" Cook - Sky art + + +exec("scripts/TR2Physics.cs"); diff --git a/scripts/admin.cs b/scripts/admin.cs new file mode 100644 index 0000000..ea8c59f --- /dev/null +++ b/scripts/admin.cs @@ -0,0 +1,612 @@ +// These have been secured against all those wanna-be-hackers. +$VoteMessage["VoteAdminPlayer"] = "Admin Player"; +$VoteMessage["VoteKickPlayer"] = "Kick Player"; +$VoteMessage["BanPlayer"] = "Ban Player"; +$VoteMessage["VoteChangeMission"] = "change the mission to"; +$VoteMessage["VoteTeamDamage", 0] = "enable team damage"; +$VoteMessage["VoteTeamDamage", 1] = "disable team damage"; +$VoteMessage["VoteTournamentMode"] = "change the server to"; +$VoteMessage["VoteFFAMode"] = "change the server to"; +$VoteMessage["VoteChangeTimeLimit"] = "change the time limit to"; +$VoteMessage["VoteMatchStart"] = "start the match"; +$VoteMessage["VoteGreedMode", 0] = "enable Hoard Mode"; +$VoteMessage["VoteGreedMode", 1] = "disable Hoard Mode"; +$VoteMessage["VoteHoardMode", 0] = "enable Greed Mode"; +$VoteMessage["VoteHoardMode", 1] = "disable Greed Mode"; +// JTL +$VoteMessage["VotePurebuild", 0] = "enable pure building"; +$VoteMessage["VotePurebuild", 1] = "disable pure building"; +$VoteMessage["VoteCascadeMode", 0] = "enable cascade mode"; +$VoteMessage["VoteCascadeMode", 1] = "disable cascade mode"; +$VoteMessage["VoteExpertMode", 0] = "enable expert mode"; +$VoteMessage["VoteExpertMode", 1] = "disable expert mode"; +$VoteMessage["VoteVehicles", 0] = "enable vehicles"; +$VoteMessage["VoteVehicles", 1] = "disable vehicles"; +$VoteMessage["VoteSatchelCharge", 0] = "enable satchel charges"; +$VoteMessage["VoteSatchelCharge", 1] = "disable satchel charges"; +$VoteMessage["VoteOnlyOwnerDeconstruct", 0] = "enable only owner deconstruct"; +$VoteMessage["VoteOnlyOwnerDeconstruct", 1] = "disable only owner deconstruct"; +$VoteMessage["VoteOnlyOwnerCascade", 0] = "enable only owner cascade"; +$VoteMessage["VoteOnlyOwnerCascade", 1] = "disable only owner cascade"; +$VoteMessage["VoteOnlyOwnerRotate", 0] = "enable only owner rotate"; +$VoteMessage["VoteOnlyOwnerRotate", 1] = "disable only owner rotate"; +$VoteMessage["VoteOnlyOwnerCubicReplace", 0] = "enable only owner cubic-replace"; +$VoteMessage["VoteOnlyOwnerCubicReplace", 1] = "disable only owner cubic-replace"; +$VoteMessage["VoteInvincibleArmors", 0] = "enable invincible armors"; +$VoteMessage["VoteInvincibleArmors", 1] = "disable invincible armors"; +$VoteMessage["VoteInvincibleDeployables", 0] = "enable invincible deployables"; +$VoteMessage["VoteInvincibleDeployables", 1] = "disable invincible deployables"; +$VoteMessage["VoteUndergroundMode", 0] = "enable underground mode"; +$VoteMessage["VoteUndergroundMode", 1] = "disable underground mode"; +$VoteMessage["VoteHazardMode", 0] = "enable hazard mode"; +$VoteMessage["VoteHazardMode", 1] = "disable hazard mode"; +$VoteMessage["VoteMTCMode", 0] = "enable MTC mode"; +$VoteMessage["VoteMTCMode", 1] = "disable MTC mode"; +$VoteMessage["VoteRemoveDeployables"] = "remove all deployables in mission"; +$VoteMessage["VoteGlobalPowerCheck"] = "remove all duplicate deployables"; +$VoteMessage["VoteRemoveDupDeployables"] = "remove all duplicate deployables"; +$VoteMessage["VoteRemoveNonPoweredDeployables"] = "remove all deployables without power"; +$VoteMessage["VoteRemoveOrphanedDeployables"] = "remove all orphaned deployables"; +$VoteMessage["VotePrison", 0] = "enable prison"; +$VoteMessage["VotePrison", 1] = "disable prison"; +$VoteMessage["VotePrisonKilling", 0] = "enable jailing killers"; +$VoteMessage["VotePrisonKilling", 1] = "disable jailing killers"; +$VoteMessage["VotePrisonTeamKilling", 0] = "enable jailing team killers"; +$VoteMessage["VotePrisonTeamKilling", 1] = "disable jailing team killers"; +$VoteMessage["VotePrisonDeploySpam", 0] = "enable jailing deploy spammers"; +$VoteMessage["VotePrisonDeploySpam", 1] = "disable jailing deploy spammers"; +$VoteMessage["VoteNerfWeapons", 0] = "enable nerf weapons"; +$VoteMessage["VoteNerfWeapons", 1] = "disable nerf weapons"; +$VoteMessage["VoteNerfDance", 0] = "enable nerf dance mode"; +$VoteMessage["VoteNerfDance", 1] = "disable nerf dance mode"; +$VoteMessage["VotenerfDeath", 0] = "enable nerf death mode"; +$VoteMessage["VotenerfDeath", 1] = "disable nerf death mode"; +$VoteMessage["VoteNerfPrison", 0] = "enable nerf prison mode"; +$VoteMessage["VoteNerfPrison", 1] = "disable nerf prison mode"; +// End JTL + +function serverCmdStartNewVote(%client, %typeName, %arg1, %arg2, %arg3, %arg4, %playerVote) +{ + //DEMO VERSION - only voteKickPlayer is allowed + if ((isDemo()) && %typeName !$= "VoteKickPlayer") + { + messageClient(%client, '', "All voting options except to kick a player are disabled in the DEMO VERSION."); + return; + } + + // haha - who gets the last laugh... No admin for you! + if( %typeName $= "VoteAdminPlayer" && (!$Host::allowAdminPlayerVotes && !%client.isSuperAdmin)) + return; + + %typePass = true; + + // if not a valid vote, turn back. + if( $VoteMessage[ %typeName ] $= "" && %typeName !$= "VoteTeamDamage" ) + if( $VoteMessage[ %typeName ] $= "" && %typeName !$= "VoteHoardMode" ) + if( $VoteMessage[ %typeName ] $= "" && %typeName !$= "VoteGreedMode" ) +// JTL + if( $VoteMessage[ %typeName ] $= "" && %typeName !$= "VotePurebuild" ) + if( $VoteMessage[ %typeName ] $= "" && %typeName !$= "VoteCascadeMode" ) + if( $VoteMessage[ %typeName ] $= "" && %typeName !$= "VoteExpertMode" ) + if( $VoteMessage[ %typeName ] $= "" && %typeName !$= "VoteVehicles" ) + if( $VoteMessage[ %typeName ] $= "" && %typeName !$= "VoteSatchelCharge" ) + if( $VoteMessage[ %typeName ] $= "" && %typeName !$= "VoteOnlyOwnerDeconstruct" ) + if( $VoteMessage[ %typeName ] $= "" && %typeName !$= "VoteOnlyOwnerCascade" ) + if( $VoteMessage[ %typeName ] $= "" && %typeName !$= "VoteOnlyOwnerRotate" ) + if( $VoteMessage[ %typeName ] $= "" && %typeName !$= "VoteOnlyOwnerCubicReplace" ) + if( $VoteMessage[ %typeName ] $= "" && %typeName !$= "VoteRemoveDeployables" ) + if( $VoteMessage[ %typeName ] $= "" && %typeName !$= "VoteGlobalPowerCheck" ) + if( $VoteMessage[ %typeName ] $= "" && %typeName !$= "VoteRemoveDupDeployables" ) + if( $VoteMessage[ %typeName ] $= "" && %typeName !$= "VoteRemoveNonPoweredDeployables" ) + if( $VoteMessage[ %typeName ] $= "" && %typeName !$= "VoteRemoveOrphanedDeployables" ) + if( $VoteMessage[ %typeName ] $= "" && %typeName !$= "VoteInvincibleArmors" ) + if( $VoteMessage[ %typeName ] $= "" && %typeName !$= "VoteInvincibleDeployables" ) + if( $VoteMessage[ %typeName ] $= "" && %typeName !$= "VoteUndergroundMode" ) + if( $VoteMessage[ %typeName ] $= "" && %typeName !$= "VoteHazardMode" ) + if( $VoteMessage[ %typeName ] $= "" && %typeName !$= "VoteMTCMode" ) + if( $VoteMessage[ %typeName ] $= "" && %typeName !$= "VotePrison" ) + if( $VoteMessage[ %typeName ] $= "" && %typeName !$= "VotePrisonKilling" ) + if( $VoteMessage[ %typeName ] $= "" && %typeName !$= "VotePrisonTeamKilling" ) + if( $VoteMessage[ %typeName ] $= "" && %typeName !$= "VotePrisonDeploySpam" ) + if( $VoteMessage[ %typeName ] $= "" && %typeName !$= "VoteNerfWeapons" ) + if( $VoteMessage[ %typeName ] $= "" && %typeName !$= "VoteNerfDance" ) + if( $VoteMessage[ %typeName ] $= "" && %typeName !$= "VoteNerfDeath" ) + if( $VoteMessage[ %typeName ] $= "" && %typeName !$= "VoteNerfPrison" ) + %typePass = false; +// End JTL + + if(( $VoteMessage[ %typeName, $TeamDamage ] $= "" && %typeName $= "VoteTeamDamage" )) + %typePass = false; +// JTL + if(( $VoteMessage[ %typeName, $Host::Purebuild ] $= "" && %typeName $= "VotePurebuild" )) + %typePass = false; + if(( $VoteMessage[ %typeName, $Host::Cascade ] $= "" && %typeName $= "VoteCascadeMode" )) + %typePass = false; + if(( $VoteMessage[ %typeName, $Host::ExpertMode ] $= "" && %typeName $= "VoteExpertMode" )) + %typePass = false; + if(( $VoteMessage[ %typeName, $Host::Vehicles ] $= "" && %typeName $= "VoteVehicles" )) + %typePass = false; + if(( $VoteMessage[ %typeName, $Host::SatchelChargeEnabled ] $= "" && %typeName $= "VoteSatchelCharge" )) + %typePass = false; + if(( $VoteMessage[ %typeName, $Host::OnlyOwnerDeconstruct ] $= "" && %typeName $= "VoteOnlyOwnerDeconstruct" )) + %typePass = false; + if(( $VoteMessage[ %typeName, $Host::OnlyOwnerCascade ] $= "" && %typeName $= "VoteOnlyOwnerCascade" )) + %typePass = false; + if(( $VoteMessage[ %typeName, $Host::OnlyOwnerRotate ] $= "" && %typeName $= "VoteOnlyOwnerRotate" )) + %typePass = false; + if(( $VoteMessage[ %typeName, $Host::OnlyOwnerCubicReplace ] $= "" && %typeName $= "VoteOnlyOwnerCubicReplace" )) + %typePass = false; + if(( $VoteMessage[ %typeName, $Host::InvincibleArmors ] $= "" && %typeName $= "VoteInvincibleArmors" )) + %typePass = false; + if(( $VoteMessage[ %typeName, $Host::InvincibleDeployables ] $= "" && %typeName $= "VoteInvincibleDeployables" )) + %typePass = false; + if(( $VoteMessage[ %typeName, $Host::AllowUnderground ] $= "" && %typeName $= "VoteUndergroundMode" )) + %typePass = false; + if(( $VoteMessage[ %typeName, $Host::Hazard::Enabled ] $= "" && %typeName $= "VoteHazardMode" )) + %typePass = false; + if(( $VoteMessage[ %typeName, $Host::MTC::Enabled ] $= "" && %typeName $= "VoteMTCMode" )) + %typePass = false; + if(( $VoteMessage[ %typeName, $Host::Prison::Enabled ] $= "" && %typeName $= "VotePrison" )) + %typePass = false; + if(( $VoteMessage[ %typeName, $Host::Prison::Kill ] $= "" && %typeName $= "VotePrisonKilling" )) + %typePass = false; + if(( $VoteMessage[ %typeName, $Host::Prison::TeamKill ] $= "" && %typeName $= "VotePrisonTeamKilling" )) + %typePass = false; + if(( $VoteMessage[ %typeName, $Host::Prison::DeploySpam ] $= "" && %typeName $= "VotePrisonDeploySpam" )) + %typePass = false; + if(( $VoteMessage[ %typeName, $Host::Nerf::Enabled ] $= "" && %typeName $= "VoteNerfWeapons" )) + %typePass = false; + if(( $VoteMessage[ %typeName, $Host::Nerf::DanceAnim ] $= "" && %typeName $= "VoteNerfDance" )) + %typePass = false; + if(( $VoteMessage[ %typeName, $Host::Nerf::DeathAnim ] $= "" && %typeName $= "VoteNerfDeath" )) + %typePass = false; + if(( $VoteMessage[ %typeName, $Host::Nerf::Prison ] $= "" && %typeName $= "VoteNerfPrison" )) + %typePass = false; +// End JTL + + if( !%typePass ) + return; // -> bye ;) + + // z0dd - ZOD, 10/03/02. This was busted, BanPlayer was never delt with. + if( %typeName $= "BanPlayer" ) + { + if( !%client.isSuperAdmin || %arg1.isAdmin ) + { + return; // -> bye ;) + } + else + { + ban( %arg1, %client ); + return; + } + } + + %isAdmin = ( %client.isAdmin || %client.isSuperAdmin ); + +// JTL + if(%typeName $= "VoteVehicles" && !%isAdmin) + if(%typeName $= "VoteVehicles" && !%isAdmin) + if(%typeName $= "VoteSatchelCharge" && !%isAdmin) + if(%typeName $= "VoteOnlyOwnerDeconstruct" && !%isAdmin) + if(%typeName $= "VoteOnlyOwnerCascade" && !%isAdmin) + if(%typeName $= "VoteOnlyOwnerRotate" && !%isAdmin) + if(%typeName $= "VoteOnlyOwnerCubicReplace" && !%isAdmin) + if(%typeName $= "VoteRemoveDeployables" && !%isAdmin) + if(%typeName $= "VoteGlobalPowerCheck" && !%isAdmin) + if(%typeName $= "VoteRemoveDupDeployables" && !%isAdmin) + if(%typeName $= "VoteRemoveNonPoweredDeployables" && !%isAdmin) + if(%typeName $= "VoteRemoveOrphanedDeployables" && !%isAdmin) + if(%typeName $= "VoteInvincibleArmors" && !%isAdmin) + if(%typeName $= "VoteInvincibleDeployables" && !%isAdmin) + if(%typeName $= "VoteUndergroundMode" && !%isAdmin) + if(%typeName $= "VoteHazardMode" && !%isAdmin) + if(%typeName $= "VoteMTCMode" && !%isAdmin) + if(%typeName $= "VotePrison" && !%isAdmin) + if(%typeName $= "VotePrisonKilling" && !%isAdmin) + if(%typeName $= "VotePrisonTeamKilling" && !%isAdmin) + if(%typeName $= "VotePrisonDeploySpam" && !%isAdmin) + if(%typeName $= "VoteNerfWeapons" && !%isAdmin) + if(%typeName $= "VoteNerfDance" && !%isAdmin) + if(%typeName $= "VoteNerfDeath" && !%isAdmin) + if(%typeName $= "VoteNerfPrison" && !%isAdmin) + %typePass = false; + + if( !%typePass ) + return; // -> bye ;) +// End JTL + + // keep these under the server's control. I win. + if( !%playerVote ) + %actionMsg = $VoteMessage[ %typeName ]; + else if( %typeName $= "VoteTeamDamage" || %typeName $= "VoteGreedMode" || %typeName $= "VoteHoardMode" ) + %actionMsg = $VoteMessage[ %typeName, $TeamDamage ]; +// JTL + else if( %typeName $= "VotePurebuild" ) + %actionMsg = $VoteMessage[ %typeName, $Host::Purebuild ]; + else if( %typeName $= "VoteCascadeMode" ) + %actionMsg = $VoteMessage[ %typeName, $Host::Cascade ]; + else if( %typeName $= "VoteExpertMode" ) + %actionMsg = $VoteMessage[ %typeName, $Host::ExpertMode ]; + else if( %typeName $= "VoteVehicles" ) + %actionMsg = $VoteMessage[ %typeName, $Host::Vehicles ]; + else if( %typeName $= "VoteSatchelCharge" ) + %actionMsg = $VoteMessage[ %typeName, $Host::SatchelChargeEnabled ]; + else if( %typeName $= "VoteOnlyOwnerDeconstruct" ) + %actionMsg = $VoteMessage[ %typeName, $Host::OnlyOwnerDeconstruct ]; + else if( %typeName $= "VoteOnlyOwnerCascade" ) + %actionMsg = $VoteMessage[ %typeName, $Host::OnlyOwnerCascade ]; + else if( %typeName $= "VoteOnlyOwnerRotate" ) + %actionMsg = $VoteMessage[ %typeName, $Host::OnlyOwnerRotate ]; + else if( %typeName $= "VoteOnlyOwnerCubicReplace" ) + %actionMsg = $VoteMessage[ %typeName, $Host::OnlyOwnerCubicReplace ]; + else if( %typeName $= "VoteInvincibleArmors" ) + %actionMsg = $VoteMessage[ %typeName, $Host::InvincibleArmors ]; + else if( %typeName $= "VoteInvincibleDeployables" ) + %actionMsg = $VoteMessage[ %typeName, $Host::InvincibleDeployables ]; + else if( %typeName $= "VoteUndergroundMode" ) + %actionMsg = $VoteMessage[ %typeName, $Host::AllowUnderground ]; + else if( %typeName $= "VoteHazardMode" ) + %actionMsg = $VoteMessage[ %typeName, $Host::Hazard::Enabled ]; + else if( %typeName $= "VoteMTCMode" ) + %actionMsg = $VoteMessage[ %typeName, $Host::MTC::Enabled ]; + else if( %typeName $= "VotePrison" ) + %actionMsg = $VoteMessage[ %typeName, $Host::Prison::Enabled ]; + else if( %typeName $= "VotePrisonKilling" ) + %actionMsg = $VoteMessage[ %typeName, $Host::Prison::Kill ]; + else if( %typeName $= "VotePrisonTeamKilling" ) + %actionMsg = $VoteMessage[ %typeName, $Host::Prison::TeamKill ]; + else if( %typeName $= "VotePrisonDeploySpam" ) + %actionMsg = $VoteMessage[ %typeName, $Host::Prison::DeploySpam ]; + else if( %typeName $= "VoteNerfWeapons" ) + %actionMsg = $VoteMessage[ %typeName, $Host::Nerf::Enabled ]; + else if( %typeName $= "VoteNerfDance" ) + %actionMsg = $VoteMessage[ %typeName, ($Host::Nerf::DanceAnim && !$Host::Nerf::DeathAnim) ]; + else if( %typeName $= "VoteNerfDeath" ) + %actionMsg = $VoteMessage[ %typeName, $Host::Nerf::DeathAnim ]; + else if( %typeName $= "VoteNerfPrison" ) + %actionMsg = $VoteMessage[ %typeName, $Host::Nerf::Prison ]; +// End JTL + else + %actionMsg = $VoteMessage[ %typeName ]; + + if( !%client.canVote && !%isAdmin ) + return; + + if ( ( !%isAdmin || ( %arg1.isAdmin && ( %client != %arg1 ) ) ) && // z0dd - ToS 4/2/02: Allow SuperAdmins to kick Admins + !( ( %typeName $= "VoteKickPlayer" ) && %client.isSuperAdmin ) ) // z0dd - ToS 4/2/02: Allow SuperAdmins to kick Admins + { + %teamSpecific = false; + %gender = (%client.sex $= "Male" ? 'he' : 'she'); + if ( Game.scheduleVote $= "" ) + { + %clientsVoting = 0; + + //send a message to everyone about the vote... + if ( %playerVote ) + { + %teamSpecific = ( %typeName $= "VoteKickPlayer" ) && ( Game.numTeams > 1 ); + %kickerIsObs = %client.team == 0; + %kickeeIsObs = %arg1.team == 0; + %sameTeam = %client.team == %arg1.team; + + if( %kickeeIsObs ) + { + %teamSpecific = false; + %sameTeam = false; + } + + if(( !%sameTeam && %teamSpecific) && %typeName !$= "VoteAdminPlayer") + { + messageClient(%client, '', "\c2Player votes must be team based."); + return; + } + + // kicking is team specific + if( %typeName $= "VoteKickPlayer" ) + { + if(%arg1.isSuperAdmin) + { + messageClient(%client, '', '\c2You can not %1 %2, %3 is a Super Admin!', %actionMsg, %arg1.name, %gender); + return; + } + + Game.kickClient = %arg1; + Game.kickClientName = %arg1.name; + Game.kickGuid = %arg1.guid; + Game.kickTeam = %arg1.team; + + if(%teamSpecific) + { + for ( %idx = 0; %idx < ClientGroup.getCount(); %idx++ ) + { + %cl = ClientGroup.getObject( %idx ); + + if (%cl.team == %client.team && !%cl.isAIControlled()) + { + messageClient( %cl, 'VoteStarted', '\c2%1 initiated a vote to %2 %3.', %client.name, %actionMsg, %arg1.name); + %clientsVoting++; + } + } + } + else + { + for ( %idx = 0; %idx < ClientGroup.getCount(); %idx++ ) + { + %cl = ClientGroup.getObject( %idx ); + if ( !%cl.isAIControlled() ) + { + messageClient( %cl, 'VoteStarted', '\c2%1 initiated a vote to %2 %3.', %client.name, %actionMsg, %arg1.name); + %clientsVoting++; + } + } + } + } + else + { + for ( %idx = 0; %idx < ClientGroup.getCount(); %idx++ ) + { + %cl = ClientGroup.getObject( %idx ); + if ( !%cl.isAIControlled() ) + { + messageClient( %cl, 'VoteStarted', '\c2%1 initiated a vote to %2 %3.', %client.name, %actionMsg, %arg1.name); + %clientsVoting++; + } + } + } + } + else if ( %typeName $= "VoteChangeMission" ) + { + for ( %idx = 0; %idx < ClientGroup.getCount(); %idx++ ) + { + %cl = ClientGroup.getObject( %idx ); + if ( !%cl.isAIControlled() ) + { + messageClient( %cl, 'VoteStarted', '\c2%1 initiated a vote to %2 %3 (%4).', %client.name, %actionMsg, %arg1, %arg2 ); + %clientsVoting++; + } + } + } + else if (%arg1 !$= 0) + { + if (%arg2 !$= 0) + { + if(%typeName $= "VoteTournamentMode") + { + %admin = getAdmin(); + if(%admin > 0) + { + for ( %idx = 0; %idx < ClientGroup.getCount(); %idx++ ) + { + %cl = ClientGroup.getObject( %idx ); + if ( !%cl.isAIControlled() ) + { + messageClient( %cl, 'VoteStarted', '\c2%1 initiated a vote to %2 Tournament Mode (%3).', %client.name, %actionMsg, %arg1); + %clientsVoting++; + } + } + } + else + { + messageClient( %client, 'clientMsg', 'There must be a server admin to play in Tournament Mode.'); + return; + } + } + else + { + for ( %idx = 0; %idx < ClientGroup.getCount(); %idx++ ) + { + %cl = ClientGroup.getObject( %idx ); + if ( !%cl.isAIControlled() ) + { + messageClient( %cl, 'VoteStarted', '\c2%1 initiated a vote to %2 %3 %4.', %client.name, %actionMsg, %arg1, %arg2); + %clientsVoting++; + } + } + } + } + else + { + for ( %idx = 0; %idx < ClientGroup.getCount(); %idx++ ) + { + %cl = ClientGroup.getObject( %idx ); + if ( !%cl.isAIControlled() ) + { + messageClient( %cl, 'VoteStarted', '\c2%1 initiated a vote to %2 %3.', %client.name, %actionMsg, %arg1); + %clientsVoting++; + } + } + } + } + else + { + for ( %idx = 0; %idx < ClientGroup.getCount(); %idx++ ) + { + %cl = ClientGroup.getObject( %idx ); + if ( !%cl.isAIControlled() ) + { + messageClient( %cl, 'VoteStarted', '\c2%1 initiated a vote to %2.', %client.name, %actionMsg); + %clientsVoting++; + } + } + } + + // open the vote hud for all clients that will participate in this vote + if(%teamSpecific) + { + for ( %clientIndex = 0; %clientIndex < ClientGroup.getCount(); %clientIndex++ ) + { + %cl = ClientGroup.getObject( %clientIndex ); + + if(%cl.team == %client.team && !%cl.isAIControlled()) + messageClient(%cl, 'openVoteHud', "", %clientsVoting, ($Host::VotePassPercent / 100)); + } + } + else + { + for ( %clientIndex = 0; %clientIndex < ClientGroup.getCount(); %clientIndex++ ) + { + %cl = ClientGroup.getObject( %clientIndex ); + if ( !%cl.isAIControlled() ) + messageClient(%cl, 'openVoteHud', "", %clientsVoting, ($Host::VotePassPercent / 100)); + } + } + + clearVotes(); + Game.voteType = %typeName; + Game.scheduleVote = schedule( ($Host::VoteTime * 1000), 0, "calcVotes", %typeName, %arg1, %arg2, %arg3, %arg4 ); + %client.vote = true; + messageAll('addYesVote', ""); + + if(!%client.team == 0) + clearBottomPrint(%client); + } + else + messageClient( %client, 'voteAlreadyRunning', '\c2A vote is already in progress.' ); + } + else + { + if ( Game.scheduleVote !$= "" && Game.voteType $= %typeName ) + { + messageAll('closeVoteHud', ""); + cancel(Game.scheduleVote); + Game.scheduleVote = ""; + } + + // if this is a superAdmin, don't kick or ban + if(%arg1 != %client) + { + if(!%arg1.isSuperAdmin) + { + // Set up kick/ban values: + if ( %typeName $= "VoteBanPlayer" || %typeName $= "VoteKickPlayer" ) + { + Game.kickClient = %arg1; + Game.kickClientName = %arg1.name; + Game.kickGuid = %arg1.guid; + Game.kickTeam = %arg1.team; + } + + //Tinman - PURE servers can't call "eval" + //Mark - True, but neither SHOULD a normal server + // - thanks Ian Hardingham + Game.evalVote(%typeName, true, %arg1, %arg2, %arg3, %arg4); + } + else + messageClient(%client, '', '\c2You can not %1 %2, %3 is a Super Admin!', %actionMsg, %arg1.name, %gender); + } + } + + %client.canVote = false; + %client.rescheduleVote = schedule( ($Host::voteSpread * 1000) + ($Host::voteTime * 1000) , 0, "resetVotePrivs", %client ); +} + +function resetVotePrivs( %client ) +{ + //messageClient( %client, '', 'You may now start a new vote.'); + %client.canVote = true; + %client.rescheduleVote = ""; +} + +function serverCmdSetPlayerVote(%client, %vote) +{ + // players can only vote once + if( %client.vote $= "" ) + { + %client.vote = %vote; + if(%client.vote == 1) + messageAll('addYesVote', ""); + else + messageAll('addNoVote', ""); + + commandToClient(%client, 'voteSubmitted', %vote); + } +} + +function calcVotes(%typeName, %arg1, %arg2, %arg3, %arg4) +{ + if(%typeName $= "voteMatchStart") + if($MatchStarted || $countdownStarted) + return; + + for ( %clientIndex = 0; %clientIndex < ClientGroup.getCount(); %clientIndex++ ) + { + %cl = ClientGroup.getObject( %clientIndex ); + messageClient(%cl, 'closeVoteHud', ""); + + if ( %cl.vote !$= "" ) + { + if ( %cl.vote ) + { + Game.votesFor[%cl.team]++; + Game.totalVotesFor++; + } + else + { + Game.votesAgainst[%cl.team]++; + Game.totalVotesAgainst++; + } + } + else + { + Game.votesNone[%cl.team]++; + Game.totalVotesNone++; + } + } + //Tinman - PURE servers can't call "eval" + //Mark - True, but neither SHOULD a normal server + // - thanks Ian Hardingham + Game.evalVote(%typeName, false, %arg1, %arg2, %arg3, %arg4); + Game.scheduleVote = ""; + Game.kickClient = ""; + clearVotes(); +} + +function clearVotes() +{ + for(%clientIndex = 0; %clientIndex < ClientGroup.getCount(); %clientIndex++) + { + %client = ClientGroup.getObject(%clientIndex); + %client.vote = ""; + messageClient(%client, 'clearVoteHud', ""); + } + + for(%team = 1; %team < 5; %team++) + { + Game.votesFor[%team] = 0; + Game.votesAgainst[%team] = 0; + Game.votesNone[%team] = 0; + Game.totalVotesFor = 0; + Game.totalVotesAgainst = 0; + Game.totalVotesNone = 0; + } +} + +// Tournament mode Stuff----------------------------------- + +function setModeFFA( %mission, %missionType ) +{ + if( $Host::TournamentMode ) + { + $Host::TournamentMode = false; + + if( isObject( Game ) ) + Game.gameOver(); + + loadMission(%mission, %missionType, false); + } +} + +//------------------------------------------------------------------ + +function setModeTournament( %mission, %missionType ) +{ + if( !$Host::TournamentMode ) + { + $Host::TournamentMode = true; + + if( isObject( Game ) ) + Game.gameOver(); + + loadMission(%mission, %missionType, false); + } +} diff --git a/scripts/chatCommands.cs b/scripts/chatCommands.cs new file mode 100644 index 0000000..34e01d8 --- /dev/null +++ b/scripts/chatCommands.cs @@ -0,0 +1,86 @@ +function chatcommands(%sender, %message) { +%cmd=getWord(%message,0); +%cmd=stripChars(%cmd,"/"); +%count=getWordCount(%message); +%args=getwords(%message,1); +%cmd="cc" @ %cmd; +if (%cmd $="ccopen") //so u can call //open instead of //opendoor + %cmd="ccopendoor"; +call(%cmd,%sender,%args); +} + +function ccopendoor(%sender,%args) { +%pos = %sender.player.getMuzzlePoint($WeaponSlot); +%vec = %sender.player.getMuzzleVector($WeaponSlot); +%targetpos = vectoradd(%pos,vectorscale(%vec,100)); +%obj = containerraycast(%pos,%targetpos,$typemasks::staticshapeobjecttype,%sender.player); +%obj = getword(%obj,0); +%dataBlock = %obj.getDataBlock(); +%className = %dataBlock.className; +%cash = %obj.amount; +%owner = %obj.owner; +%obj.issliding = 0; +if (%obj.Collision == true) //if is a colition door + return; //stop here +if (%obj.canmove == false) //if it cant move + return; //stop here +if (%obj.isdoor != 1 && %hitobj.getdatablock().getname() !$="DeployedTdoor"){ + messageclient(%sender, 'MsgClient', '\c5No door in range.'); + return; + } +if (!isobject(%obj)) { + messageclient(%sender, 'MsgClient', '\c5No door in range.'); + return; + } +if (%obj.powercontrol == 1) { + messageclient(%sender, 'MsgClient', '\c5This door is controlled by a power supply.'); + return; + } + %pass = %args; +if (%obj.pw $= %pass) { + if (%obj.toggletype ==1){ + if (%obj.moving $="close" || %obj.moving $="" || %going $="opening"){ + schedule(10,0,"open",%obj); + } + else if (%obj.moving $="open" || %going $="closeing"){ + schedule(10,0,"close",%obj); + } + } + else + schedule(10,0,"open",%obj); +} +if (%obj.pw !$= %pass) + messageclient(%sender,'MsgClient',"\c2Password Denied."); + +} + +function ccsetdoorpass(%sender,%args){ +%pos=%sender.player.getMuzzlePoint($WeaponSlot); +%vec = %sender.player.getMuzzleVector($WeaponSlot); +%targetpos=vectoradd(%pos,vectorscale(%vec,100)); +%obj=containerraycast(%pos,%targetpos,$typemasks::staticshapeobjecttype,%sender.player); +%obj=getword(%obj,0); +%dataBlock = %obj.getDataBlock(); +%className = %dataBlock.className; +if (%classname !$= "door") { +messageclient(%sender, 'MsgClient', '\c2No door in range.'); +return; +} +if (%obj.owner!=%sender && %obj.owner !$="") +messageclient(%sender, 'MsgClient', '\c2You do not own this door.'); +if (!isobject(%obj)) +messageclient(%sender, 'MsgClient', '\c2No door in range.'); +if (%obj.Collision $= true) { +messageclient(%sender, 'MsgClient', '\c2Collision doors can not have passwords.'); +return; +} +if(isobject(%obj) && %obj.owner==%sender) { +%pw=getword(%args,0); +%obj.pw=%pw; +messageclient(%sender, 'MsgClient', '\c2Password set, password is %1.',%pw); +} +} + +function ccbf(%sender,%args) { +buyFavorites(%sender); +} diff --git a/scripts/client.cs b/scripts/client.cs new file mode 100644 index 0000000..e26ed48 --- /dev/null +++ b/scripts/client.cs @@ -0,0 +1,2132 @@ +//---------------------------------------------------------------------------- + +//---------------------------------------------------------------------------- + +function SAD(%password) +{ + if(%password !$= "") + commandToServer('SAD', %password); +} + +function SADSetPassword(%password) +{ + commandToServer('SADSetPassword', %password); +} + +function use(%data) +{ + // %data is currently the datablock name of the item + commandToServer('use',%data); +} + +function throw(%data) +{ + // %data is currently the datablock name of the item + commandToServer('throw',%data); +} + +function giveAll() +{ + commandToServer('giveAll'); +} + +function clientCmdSetPlayContent() +{ + if ( $LaunchMode $= "InteriorView" ) + Canvas.setContent( interiorPreviewGui ); + else if ( $LaunchMode $= "TSShow" ) + Canvas.setContent( TSShowGui ); + else + Canvas.setContent( Playgui ); +} + +function clientCmdPickTeamMenu( %teamA, %teamB ) +{ + ClientCmdSetHudMode("PickTeam"); + PickTeamAButton.text = getTaggedString( %teamA ); + PickTeamBButton.text = getTaggedString( %teamB ); + PickTeamFrame.setTitle( "Pick Team" ); + + Canvas.pushDialog( PickTeamDlg ); +} + +function clientCmdProcessPickTeam( %option ) +{ + if( %option !$= "" && %option <= 4 ) + CommandToServer( 'clientPickedTeam', %option ); + else if( %option !$= "" && %option == 5 ) + disconnect(); + + Canvas.popDialog( PickTeamDlg ); +} + +new MessageVector(HudMessageVector); + +$LastHudTarget = 0; + +function addMessageHudLine(%text) +{ + %adjustPos = false; + if( chatPageDown.isVisible() ) + { + %adjustPos = true; + %origPosition = chatHud.position; + } + + //add the message... + while( !chatPageDown.isVisible() && HudMessageVector.getNumLines() && (HudMessageVector.getNumLines() >= $pref::HudMessageLogSize)) + { + %tag = HudMessageVector.getLineTag(0); + if(%tag != 0) + %tag.delete(); + HudMessageVector.popFrontLine(); + } + HudMessageVector.pushBackLine(%text, $LastHudTarget); + $LastHudTarget = 0; + + //now that we've added the message, see if we need to reset the position + if ( %adjustPos ) + { + chatPageDown.setVisible(true); + ChatPageDown.position = ( firstWord( outerChatHud.extent ) - 20 ) @ " " @ ( $chatScrollLenY[$Pref::chatHudLength] - 6 ); + chatHud.position = %origPosition; + } + else + chatPageDown.setVisible(false); + +} + +function pageUpMessageHud() +{ + //find out the text line height + %textHeight = chatHud.profile.fontSize; + if (%textHeight <= 0) + %textHeight = 12; + + //find out how many lines per page are visible + %chatScrollHeight = getWord(chatHud.getGroup().getGroup().extent, 1); + if (%chatScrollHeight <= 0) + return; + + %pageLines = mFloor(%chatScrollHeight / %textHeight) - 1; + if (%pageLines <= 0) + %pageLines = 1; + + //see how many lines we actually can scroll up: + %chatPosition = -1 * getWord(chatHud.position, 1); + %linesToScroll = mFloor((%chatPosition / %textHeight) + 0.5); + if (%linesToScroll <= 0) + return; + + if (%linesToScroll > %pageLines) + %scrollLines = %pageLines; + else + %scrollLines = %linesToScroll; + + //now set the position + chatHud.position = firstWord(chatHud.position) SPC (getWord(chatHud.position, 1) + (%scrollLines * %textHeight)); + + //display the pageup icon + ChatPageDown.position = ( firstWord( outerChatHud.extent ) - 20 ) @ " " @ ( $chatScrollLenY[$pref::chatHudLength] - 6 ); + chatPageDown.setVisible(true); +} + +function pageDownMessageHud() +{ + //find out the text line height + %textHeight = chatHud.profile.fontSize; + if (%textHeight <= 0) + %textHeight = 12; + + //find out how many lines per page are visible + %chatScrollHeight = getWord(chatHud.getGroup().getGroup().extent, 1); + if (%chatScrollHeight <= 0) + return; + + %pageLines = mFloor(%chatScrollHeight / %textHeight) - 1; + if (%pageLines <= 0) + %pageLines = 1; + + //see how many lines we actually can scroll down: + %chatPosition = getWord(chatHud.extent, 1) - %chatScrollHeight + getWord(chatHud.position, 1); + %linesToScroll = mFloor((%chatPosition / %textHeight) + 0.5); + if (%linesToScroll <= 0) + return; + + if (%linesToScroll > %pageLines) + %scrollLines = %pageLines; + else + %scrollLines = %linesToScroll; + + //now set the position + chatHud.position = firstWord(chatHud.position) SPC (getWord(chatHud.position, 1) - (%scrollLines * %textHeight)); + + //see if we have should (still) display the pagedown icon + if (%scrollLines < %linesToScroll) + { + chatPageDown.setVisible(true); + ChatPageDown.position = ( firstWord( outerChatHud.extent ) - 20 ) @ " " @ ( $chatScrollLenY[$Pref::chatHudLength] - 6 ); + } + else + chatPageDown.setVisible(false); +} + +$cursorControlled = true; + +function CursorOff() +{ + if ( $cursorControlled ) + lockMouse(true); + Canvas.cursorOff(); +} + +function CursorOn() +{ + if ( $cursorControlled ) + lockMouse(false); + Canvas.cursorOn(); + Canvas.setCursor(DefaultCursor); +} + +function toggleCursorControl() +{ + // If the user manually toggles the mouse control, lock or unlock for them + if ( $cursorControlled ) + $cursorControlled = false; + else + $cursorControlled = true; + lockMouse($cursorControlled); +} + +if ( $platform $= "linux" ) + GlobalActionMap.bindCmd(keyboard, "ctrl g", "", "toggleCursorControl();"); + +function toggleNetDisplayHud(%val) +{ + if(%val) + { + if(NetGraphHudFrame.isVisible()) + { + NetGraphHudFrame.setVisible(false); + NetBarHudFrame.setVisible(true); + } + else if(NetBarHudFrame.isVisible()) + { + NetBarHudFrame.setVisible(false); + } + else + NetGraphHudFrame.setVisible(true); + } +} + +function PlayGui::onWake(%this) +{ + // Make sure the shell hum is off: + if ( $HudHandle[shellScreen] !$= "" ) + { + alxStop( $HudHandle[shellScreen] ); + $HudHandle[shellScreen] = ""; + } + + $enableDirectInput = "1"; + activateDirectInput(); + + // chat hud dialog + Canvas.pushDialog( MainChatHud ); + chatHud.attach(HudMessageVector); + + // just update the action map here, the huds should be properly setup + updateActionMaps(); + + // hack city - these controls are floating around and need to be clamped + schedule(0, 0, "refreshCenterTextCtrl"); + schedule(0, 0, "refreshBottomTextCtrl"); + + // update the network graph prefs + NetGraphHud.getPrefs(); +} + +function refreshBottomTextCtrl() +{ + BottomPrintText.position = "0 0"; +} + +function refreshCenterTextCtrl() +{ + CenterPrintText.position = "0 0"; +} + +function PlayGui::onSleep(%this) +{ + Canvas.popDialog( MainChatHud ); + + //pop all possible keymaps + moveMap.pop(); + if ( isObject( passengerKeys ) ) + passengerKeys.pop(); + if ( isObject( observerBlockMap ) ) + observerBlockMap.pop(); + if ( isObject( observerMap ) ) + observerMap.pop(); + //flyingCameraMove.pop(); +} + +function onConnectRequestRejected( %msg ) +{ + switch$(%msg) + { + case "CR_INVALID_CONNECT_PACKET": + %error = "Network error - badly formed network packet - this should not happen!"; + case "CR_AUTHENTICATION_FAILED": + %error = "Failed to authenticate with server. Please restart TRIBES 2 and try again."; + case "CR_YOUAREBANNED": + %error = "You are not allowed to play on this server."; + case "CR_SERVERFULL": + %error = "This server is full."; + default: + %error = "Connection error. Please try another server. Error code: (" @ %msg @ ")"; + } + DisconnectedCleanup(); + MessageBoxOK( "REJECTED", %error); +} + +function onChallengeRequestRejected( %msg ) +{ + CloseMessagePopup(); + DisconnectedCleanup(); + switch$(%msg) + { + case "PASSWORD": + if ( $JoinGamePassword $= "" ) + Canvas.pushDialog( PasswordDlg ); + else + { + $JoinGamePassword = ""; + MessageBoxOK( "REJECTED", "That password is incorrect."); + } + return; + case "CHR_PROTOCOL_SERVER": + %error = "Incompatible protocol version: The server is running an older, incompatible version of Tribes 2."; + case "CHR_PROTOCOL": + %error = "Incompatible protocol version: You must upgrade your game version to play on this server."; + case "CHR_NOT_AUTHENTICATED": + %error = "This is an online server - you must be logged in to play on it."; + case "CHR_INVALID_SERVER_PACKET": + %error = "Invalid server response packet. This should not happen."; + case "WS_PeerAuthServer_ExpiredClientCertificate": + %error = "Authentication error - please restart TRIBES 2 and try again."; + default: + %error = "Connection challenge error. Please try another server. Error code: (" @ %msg @ ")"; + } + MessageBoxOK( "REJECTED", %error ); +} + +function onConnectRequestTimedOut() +{ + DisconnectedCleanup(); + MessageBoxOK( "TIMED OUT", "Your connection to the server timed out." ); +} + +function onConnectionToServerTimedOut() +{ + DisconnectedCleanup(); + MessageBoxOK( "TIMED OUT", "Your connection to the server timed out."); +} + +function onConnectionToServerLost( %msg ) +{ + DisconnectedCleanup(); + if ( %msg $= "" ) + %msg = "Your connection to the server was lost."; + MessageBoxOK( "DISCONNECTED", %msg ); +} + +// Client voting functions: +function startNewVote(%name, %arg1, %arg2, %arg3, %arg4, %playerVote) +{ + if ( %arg1 $= "" ) + %arg1 = 0; + if ( %arg2 $= "" ) + %arg2 = 0; + if ( %arg3 $= "" ) + %arg3 = 0; + if ( %arg4 $= "" ) + %arg4 = 0; + if ( %playerVote $= "" ) + %playerVote = 0; + + commandToServer('startNewVote', %name, %arg1, %arg2, %arg3, %arg4, %playerVote); +} + +function setPlayerVote(%vote) +{ + commandToServer('setPlayerVote', %vote); +} + +function ClientCmdVoteSubmitted(%type) +{ + clientCmdClearBottomPrint(); + + if(%type) + alxPlay(VoteAgainstSound, 0, 0, 0); + else + alxPlay(VoteForSound, 0, 0, 0); +} +// End client voting functions. + +//-------------------------------------------------------------------------- +// Player pref functions: +function getPlayerPrefs( %player ) +{ + %voiceMuted = false; + if ( $PlayingOnline ) + { + if ( !%player.isSmurf ) + { + %record = queryPlayerDatabase( %player.guid ); + if ( %record !$= "" ) + { + if ( firstWord( %record ) == 1 ) + { + %player.chatMuted = true; + commandToServer( 'TogglePlayerMute', %player.clientId ); + } + + %voiceMuted = getWord( %record, 1 ) == 1; + } + } + else + %voiceMuted = true; // For now, automatically mute smurfs + } + + commandToServer( 'ListenTo', %player.clientId, !%voiceMuted, false ); +} + +//-------------------------------------------------------------------------- +function handlePlayerMuted( %msgType, %msgString, %name, %client, %mute ) +{ + if ( isObject( $PlayerList[%client] ) ) + { + $PlayerList[%client].chatMuted = %mute; + if ( $PlayingOnline && !$PlayerList[%client].isSmurf && $PlayerList[%client].guid > 0 ) + setPlayerTextMuted( $PlayerList[%client].guid, %mute ); + } +} + +//-------------------------------------------------------------------------- +function clientCmdEndBomberSight() +{ + PlayGui.remove($bombSightHud); +} + +function clientCmdRemoveReticle() +{ + reticleHud.setBitmap(""); + reticleFrameHud.setVisible(false); +} + +function clientCmdSetBeaconNames(%target, %marker, %vehicle) +{ + setBeaconNames(%target, %marker, %vehicle); +} + +function clientCmdStartBomberSight() +{ + $bombSightHud = new HudBombSight(bombSightName) { + profile = "GuiDefaultProfile"; + horizSizing = "right"; + vertSizing = "bottom"; + position = "286 206"; + extent = "67 67"; + minExtent = "8 8"; + visible = "1"; + setFirstResponder = "0"; + modal = "1"; + helpTag = "0"; + minDisplayHeight = "20"; + }; + PlayGui.add($bombSightHud); +} + +function tempShowSpeed(%client) +{ + if(!$tmpSpeedShow) + $tmpSpeedShow = true; + else + $tmpSpeedShow = false; + commandToClient(%client, 'toggleSpeed', %client, $tmpSpeedShow); +} + +function clientCmdToggleSpeed(%client, %toggle) +{ + if(%toggle) { + %tempSpeedHud = new GuiTextCtrl(tmpSpeed) { + profile = "GuiTempSpeedProfile"; + horizSizing = "center"; + vertSizing = "top"; + position = "175 200"; + extent = "120 50"; + minExtent = "8 8"; + visible = "1"; + setFirstResponder = "0"; + modal = "1"; + }; + PlayGui.add(%tempSpeedHud); + %client.updateTempSpeed(%client); + } + else { + cancel(%client.tmpSpeedCheck); + tmpSpeed.delete(); + } +} + +function GameConnection::updateTempSpeed(%client) +{ + commandToClient(%client, 'getTempSpeed'); + %client.tmpSpeedCheck = %client.schedule(100, "updateTempSpeed", %client); +} + +function clientCmdGetTempSpeed() +{ + %vel = getControlObjectSpeed(); + tmpSpeed.setValue(%vel); +} + +function clientCmdInitLoadClientFavorites() +{ + loadFavorite($pref::FavCurrentSelect); +} + +function clientCmdToggleDashHud(%val) +{ + if(!%val) { + if(isObject(vDiagramHud)) + { + vDiagramHud.delete(); + cancel(dashboardHud.speedCheck); + vSpeedBox.delete(); + } + if(isObject(vOverheadHud)) + vOverheadHud.delete(); + if(isObject(vEnergyFrame)) + vEnergyFrame.delete(); + if(isObject(vDamageFrame)) + vDamageFrame.delete(); + if(isObject(vAltitudeBox)) + { + cancel(dashboardHud.altitudeCheck); + vAltitudeBox.delete(); + } + if(isObject(vWeaponOne)) + vWeaponOne.delete(); + if(isObject(vWeaponTwo)) + vWeaponTwo.delete(); + if(isObject(vWeaponThree)) + vWeaponThree.delete(); + if(isObject(vWeapHiliteOne)) + vWeapHiliteOne.delete(); + if(isObject(vWeapHiliteTwo)) + vWeapHiliteTwo.delete(); + if(isObject(vWeapHiliteThree)) + vWeapHiliteThree.delete(); + if(isObject(vPassengerHud)) + vPassengerHud.delete(); + if(isObject(bombardierHud)) + bombardierHud.delete(); + if(isObject(turreteerHud)) + turreteerHud.delete(); + // reset in case of vehicle-specific reticle + //reticleHud.setBitmap(""); + //reticleFrameHud.setVisible(false); + } + dashboardHud.setVisible(%val); +} + +function addEnergyGauge( %vehType ) +{ + switch$ (%vehType) + { + case "Assault" or "Bomber": + dashboardHud.nrgBar = new HudBitmapCtrl(vEnergyFrame) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "160 80"; + extent = "118 19"; + minExtent = "8 8"; + visible = "1"; + bitmap = "gui/hud_veh_new_dashpiece_5"; + opacity = "0.8"; + + new HudEnergy(vEnergyBar) { + profile = "GuiDefaultProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "0 0"; + extent = "118 19"; + minExtent = "8 8"; + visible = "1"; + fillColor = "0.353000 0.373000 0.933000 0.800000"; + frameColor = "0.000000 1.000000 0.000000 1.000000"; + autoCenter = "0"; + autoResize = "0"; + displayMounted = true; + bitmap = "gui/hud_veh_new_dashpiece_5"; + verticalFill = false; + subRegion = "4 5 98 5"; + pulseRate = "500"; + pulseThreshold = "0.3"; + //modColor = "1.000000 0.500000 0.000000 1.000000"; + }; + + new HudCapacitor(vCapBar) { + profile = "GuiDefaultProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "0 8"; + extent = "118 8"; + minExtent = "8 8"; + visible = "1"; + fillColor = "1.000 0.729 0.301 0.800000"; + frameColor = "0.000000 1.000000 0.000000 1.000000"; + autoCenter = "0"; + autoResize = "0"; + displayMounted = true; + bitmap = "gui/hud_veh_new_dashpiece_5"; + verticalFill = false; + subRegion = "4 5 98 5"; + pulseRate = "500"; + pulseThreshold = "0.3"; + //modColor = "1.000000 0.500000 0.000000 1.000000"; + }; + }; + dashboardHud.add(dashboardHud.nrgBar); + + default: + dashboardHud.nrgBar = new HudBitmapCtrl(vEnergyFrame) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "160 80"; + extent = "118 19"; + minExtent = "8 8"; + visible = "1"; + bitmap = "gui/hud_veh_new_dashpiece_5"; + opacity = "0.8"; + + new HudEnergy(vEnergyBar) { + profile = "GuiDefaultProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "0 0"; + extent = "118 19"; + minExtent = "8 8"; + visible = "1"; + fillColor = "0.353000 0.373000 0.933000 0.800000"; + frameColor = "0.000000 1.000000 0.000000 1.000000"; + autoCenter = "0"; + autoResize = "0"; + displayMounted = true; + bitmap = "gui/hud_veh_new_dashpiece_5"; + verticalFill = false; + subRegion = "4 5 98 10"; + pulseRate = "500"; + pulseThreshold = "0.3"; + //modColor = "1.000000 0.500000 0.000000 1.000000"; + }; + }; + dashboardHud.add(dashboardHud.nrgBar); + } +} + +function clientCmdShowVehicleGauges(%vehType, %node) +{ + //if(!((%vehType $= "Bomber" || %vehType $= "Assault") && %node > 0)) + if(%node == 0) + { + // common elements that show up on all vehicle pilot HUDs + dashboardHud.diagram = new HudBitmapCtrl(vDiagramHud) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "200 10"; + extent = "176 108"; + minExtent = "8 8"; + visible = "1"; + bitmap = "gui/hud_veh_new_dash"; + opacity = "0.8"; + }; + dashboardHud.add(dashboardHud.diagram); + + dashboardHud.vehDiagram = new HudBitmapCtrl(vOverheadHud) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "256 0"; + extent = "128 128"; + minExtent = "8 8"; + visible = "1"; + bitmap = ""; + opacity = "1.0"; + }; + dashboardHud.add(dashboardHud.vehDiagram); + + addEnergyGauge( %vehType ); + + dashboardHud.dmgBar = new HudBitmapCtrl(vDamageFrame) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "361 80"; + extent = "118 19"; + minExtent = "8 8"; + visible = "1"; + bitmap = "gui/hud_veh_new_dashpiece_4"; + opacity = "0.8"; + + new HudDamage(vDamageBar) { + profile = "GuiDefaultProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "0 0"; + extent = "118 19"; + minExtent = "8 8"; + visible = "1"; + fillColor = "0.000000 1.0000 0.000000 0.800000"; + frameColor = "0.000000 1.000000 0.000000 0.000000"; + bitmap = "gui/hud_veh_new_dashpiece_4"; + verticalFill = false; + displayMounted = true; + opacity = "0.8"; + subRegion = "18 5 97 10"; + pulseRate = "500"; + pulseThreshold = "0.3"; + //modColor = "1.000000 0.500000 0.000000 1.000000"; + }; + }; + dashboardHud.add(dashboardHud.dmgBar); + + dashboardHud.speedBox = new GuiControl(vSpeedBox) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "210 47"; + extent = "40 40"; + minExtent = "8 8"; + visible = "1"; + + new GuiTextCtrl(vSpeedText) { + profile = "GuiDashTextProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "3 15"; + extent = "18 15"; + minExtent = "8 8"; + visible = "1"; + text = "test"; + }; + new GuiTextCtrl(vSpeedTxtLbl) { + profile = "GuiDashTextProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "18 15"; + extent = "27 15"; + minExtent = "8 8"; + visible = "1"; + text = "KPH"; + }; + }; + dashboardHud.add(dashboardHud.speedBox); + + dashboardHud.updateSpeed(); + } + + switch$ (%vehType) { + case "Shrike" : + vOverheadHud.setBitmap("gui/hud_veh_icon_shrike"); + // add altitude box for flying vehicles + dashboardHud.altBox = new HudBitmapCtrl(vAltitudeBox) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "371 56"; + extent = "68 22"; + minExtent = "8 8"; + bitmap = "gui/hud_veh_new_dashpiece_1"; + visible = "1"; + opacity = "0.8"; + + new GuiTextCtrl(vAltitudeText) { + profile = "GuiDashTextProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "19 5"; + extent = "18 15"; + minExtent = "8 8"; + visible = "1"; + text = "test"; + }; + new GuiTextCtrl(vAltitudeTxtLbl) { + profile = "GuiDashTextProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "40 5"; + extent = "12 15"; + minExtent = "8 8"; + visible = "1"; + text = "M"; + }; + }; + dashboardHud.add(dashboardHud.altBox); + dashboardHud.updateAltitude(); + // add right-hand weapons box and highlight + dashboardHud.weapon = new GuiControl(vWeapHiliteOne) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "358 22"; + extent = "80 33"; + minExtent = "8 8"; + visible = "1"; + + new HudBitmapCtrl(vWeapBkgdOne) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "0 0"; + extent = "82 40"; + minExtent = "8 8"; + bitmap = "gui/hud_veh_new_dashpiece_2"; + visible = "1"; + opacity = "0.8"; + + new HudBitmapCtrl(vWeapIconOne) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "28 6"; + extent = "25 25"; + minExtent = "8 8"; + bitmap = "gui/hud_blaster"; + visible = "1"; + opacity = "0.8"; + }; + }; + }; + dashboardHud.add(dashboardHud.weapon); + // change to shrike reticle + reticleHud.setBitmap("gui/hud_ret_shrike"); + reticleFrameHud.setVisible(false); + + case "Bomber" : + if(%node == 1) + { + // bombardier hud + dashboardHud.bHud = new GuiControl(bombardierHud) { + profile = "GuiDefaultProfile"; + horizSizing = "center"; + vertSizing = "top"; + position = "200 75"; + extent = "240 50"; + minExtent = "8 8"; + visible = "1"; + + new HudBitmapCtrl(vWeap1Hilite) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "bottom"; + position = "18 9"; + extent = "80 44"; + minExtent = "8 8"; + visible = "1"; + bitmap = "gui/hud_veh_new_hilite_left"; + opacity = "0.3"; + }; + new HudBitmapCtrl(vWeap2Hilite) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "bottom"; + position = "141 9"; + extent = "80 44"; + minExtent = "8 8"; + visible = "0"; + bitmap = "gui/hud_veh_new_hilite_right"; + opacity = "0.3"; + }; + new HudBitmapCtrl(vWeap3Hilite) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "bottom"; + position = "99 9"; + extent = "40 44"; + minExtent = "8 8"; + visible = "0"; + bitmap = "gui/hud_veh_new_hilite_middle"; + opacity = "0.3"; + }; + + new HudBitmapCtrl(bombardierFrame) { + profile = "GuiDashBoxProfile"; + horizSizing = "center"; + vertSizing = "bottom"; + position = "20 8"; + extent = "200 40"; + minExtent = "8 8"; + visible = "1"; + bitmap = "gui/hud_veh_new_bombardier_dash"; + opacity = "1.0"; + + new HudBitmapCtrl(vWeaponOne) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "bottom"; + position = "28 5"; + extent = "25 25"; + minExtent = "8 8"; + visible = "1"; + bitmap = "gui/hud_blaster"; + }; + + new HudBitmapCtrl(vWeaponTwo) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "bottom"; + position = "87 6"; + extent = "25 25"; + minExtent = "8 8"; + visible = "1"; + bitmap = "gui/hud_targetlaser"; + }; + + new HudBitmapCtrl(vWeaponThree) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "bottom"; + position = "147 6"; + extent = "25 25"; + minExtent = "8 8"; + visible = "1"; + bitmap = "gui/hud_veh_bomb"; + }; + }; + }; + dashboardHud.add(dashboardHud.bHud); + + dashboardHud.nrgBar = new HudBitmapCtrl(vEnergyFrame) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "110 95"; + extent = "118 19"; + minExtent = "8 8"; + visible = "1"; + flipVertical = true; + bitmap = "gui/hud_veh_new_dashpiece_5"; + opacity = "0.8"; + + new HudEnergy(vEnergyBar) { + profile = "GuiDefaultProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "0 0"; + extent = "118 19"; + minExtent = "8 8"; + visible = "1"; + fillColor = "0.353000 0.373000 0.933000 0.800000"; + frameColor = "0.000000 1.000000 0.000000 1.000000"; + autoCenter = "0"; + autoResize = "0"; + displayMounted = true; + bitmap = "gui/hud_veh_new_dashpiece_5"; + verticalFill = false; + subRegion = "4 5 98 5"; + pulseRate = "500"; + pulseThreshold = "0.3"; + //modColor = "1.000000 0.500000 0.000000 1.000000"; + }; + new HudCapacitor(vCapBar) { + profile = "GuiDefaultProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "0 8"; + extent = "118 8"; + minExtent = "8 8"; + visible = "1"; + fillColor = "1.000 0.729 0.301 0.800000"; + frameColor = "0.000000 1.000000 0.000000 1.000000"; + autoCenter = "0"; + autoResize = "0"; + displayMounted = true; + bitmap = "gui/hud_veh_new_dashpiece_5"; + verticalFill = false; + subRegion = "4 5 98 5"; + pulseRate = "500"; + pulseThreshold = "0.3"; + //modColor = "1.000000 0.500000 0.000000 1.000000"; + }; + }; + dashboardHud.add(dashboardHud.nrgBar); + + dashboardHud.dmgBar = new HudBitmapCtrl(vDamageFrame) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "410 95"; + extent = "118 19"; + minExtent = "8 8"; + visible = "1"; + flipVertical = true; + bitmap = "gui/hud_veh_new_dashpiece_4"; + opacity = "0.8"; + + new HudDamage(vDamageBar) { + profile = "GuiDefaultProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "0 0"; + extent = "118 19"; + minExtent = "8 8"; + visible = "1"; + fillColor = "0.000000 1.0000 0.000000 0.800000"; + frameColor = "0.000000 1.000000 0.000000 0.000000"; + bitmap = "gui/hud_veh_new_dashpiece_4"; + verticalFill = false; + displayMounted = true; + opacity = "0.8"; + subRegion = "18 5 97 10"; + pulseRate = "500"; + pulseThreshold = "0.3"; + //modColor = "1.000000 0.500000 0.000000 1.000000"; + }; + }; + dashboardHud.add(dashboardHud.dmgBar); + $numVWeapons = 3; + reticleHud.setBitmap("gui/hud_ret_shrike"); + reticleFrameHud.setVisible(false); + } + else if(%node == 0) + { + // pilot dashboard hud + vOverheadHud.setBitmap("gui/hud_veh_icon_bomber"); + // add altitude box for flying vehicles + dashboardHud.altBox = new HudBitmapCtrl(vAltitudeBox) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "371 56"; + extent = "68 22"; + minExtent = "8 8"; + bitmap = "gui/hud_veh_new_dashpiece_1"; + visible = "1"; + opacity = "0.8"; + + new GuiTextCtrl(vAltitudeText) { + profile = "GuiDashTextProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "19 5"; + extent = "18 15"; + minExtent = "8 8"; + visible = "1"; + text = "test"; + }; + new GuiTextCtrl(vAltitudeTxtLbl) { + profile = "GuiDashTextProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "40 5"; + extent = "12 15"; + minExtent = "8 8"; + visible = "1"; + text = "M"; + }; + }; + dashboardHud.add(dashboardHud.altBox); + dashboardHud.updateAltitude(); + } + else + { + // tailgunner hud + dashboardHud.vehDiagram = new HudBitmapCtrl(vOverheadHud) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "256 0"; + extent = "128 128"; + minExtent = "8 8"; + visible = "1"; + bitmap = "gui/hud_veh_icon_bomber"; + opacity = "1.0"; + }; + dashboardHud.add(dashboardHud.vehDiagram); + + dashboardHud.nrgBar = new HudBitmapCtrl(vEnergyFrame) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "177 50"; + extent = "118 19"; + minExtent = "8 8"; + visible = "1"; + bitmap = "gui/hud_veh_new_dashpiece_5"; + flipVertical = true; + opacity = "0.8"; + + new HudEnergy(vEnergyBar) { + profile = "GuiDefaultProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "0 0"; + extent = "118 19"; + minExtent = "8 8"; + visible = "1"; + fillColor = "0.353000 0.373000 0.933000 0.800000"; + frameColor = "0.000000 1.000000 0.000000 1.000000"; + autoCenter = "0"; + autoResize = "0"; + displayMounted = true; + bitmap = "gui/hud_veh_new_dashpiece_5"; + verticalFill = false; + subRegion = "4 5 98 10"; + pulseRate = "500"; + pulseThreshold = "0.3"; + }; + }; + dashboardHud.add(dashboardHud.nrgBar); + + dashboardHud.dmgBar = new HudBitmapCtrl(vDamageFrame) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "345 50"; + extent = "118 19"; + minExtent = "8 8"; + visible = "1"; + bitmap = "gui/hud_veh_new_dashpiece_4"; + flipVertical = true; + opacity = "0.8"; + + new HudDamage(vDamageBar) { + profile = "GuiDefaultProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "0 0"; + extent = "118 19"; + minExtent = "8 8"; + visible = "1"; + fillColor = "0.000000 1.0000 0.000000 0.800000"; + frameColor = "0.000000 1.000000 0.000000 0.000000"; + bitmap = "gui/hud_veh_new_dashpiece_4"; + verticalFill = false; + displayMounted = true; + opacity = "0.8"; + subRegion = "18 5 97 10"; + pulseRate = "500"; + pulseThreshold = "0.3"; + }; + }; + dashboardHud.add(dashboardHud.dmgBar); + } + if(%node != 1) + { + // passenger slot "dots" + vOverheadHud.passengerHud = new GuiControl(vPassengerHud) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "0 0"; + extent = "101 101"; + minExtent = "8 8"; + visible = "1"; + + new GuiBitmapCtrl(vPassenger0Slot) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "59 24"; + extent = "10 10"; + minExtent = "3 3"; + visible = "0"; + bitmap = "gui/hud_veh_seatdot"; + }; + new GuiBitmapCtrl(vPassenger1Slot) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "59 39"; + extent = "10 10"; + minExtent = "3 3"; + visible = "0"; + bitmap = "gui/hud_veh_seatdot"; + }; + new GuiBitmapCtrl(vPassenger2Slot) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "59 84"; + extent = "10 10"; + minExtent = "3 3"; + visible = "0"; + bitmap = "gui/hud_veh_seatdot"; + }; + }; + vOverheadHud.add(vOverheadHud.passengerHud); + } + case "HAPC" : + if(%node == 0) + { + vOverheadHud.setBitmap("gui/hud_veh_icon_hapc"); + // add altitude box for flying vehicles + dashboardHud.altBox = new HudBitmapCtrl(vAltitudeBox) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "371 56"; + extent = "68 22"; + minExtent = "8 8"; + bitmap = "gui/hud_veh_new_dashpiece_1"; + visible = "1"; + opacity = "0.8"; + + new GuiTextCtrl(vAltitudeText) { + profile = "GuiDashTextProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "19 5"; + extent = "18 15"; + minExtent = "8 8"; + visible = "1"; + text = "test"; + }; + new GuiTextCtrl(vAltitudeTxtLbl) { + profile = "GuiDashTextProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "40 5"; + extent = "12 15"; + minExtent = "8 8"; + visible = "1"; + text = "M"; + }; + }; + dashboardHud.add(dashboardHud.altBox); + updateVehicleAltitude(); + dashboardHud.updateAltitude(); + + } + else + { + // passenger hud + dashboardHud.vehDiagram = new HudBitmapCtrl(vOverheadHud) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "256 0"; + extent = "128 128"; + minExtent = "8 8"; + visible = "1"; + bitmap = "gui/hud_veh_icon_hapc"; + opacity = "1.0"; + }; + dashboardHud.add(dashboardHud.vehDiagram); + + dashboardHud.nrgBar = new HudBitmapCtrl(vEnergyFrame) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "180 30"; + extent = "118 19"; + minExtent = "8 8"; + visible = "1"; + bitmap = "gui/hud_veh_new_dashpiece_5"; + flipVertical = true; + opacity = "0.8"; + + new HudEnergy(vEnergyBar) { + profile = "GuiDefaultProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "0 0"; + extent = "118 19"; + minExtent = "8 8"; + visible = "1"; + fillColor = "0.353000 0.373000 0.933000 0.800000"; + frameColor = "0.000000 1.000000 0.000000 1.000000"; + autoCenter = "0"; + autoResize = "0"; + displayMounted = true; + bitmap = "gui/hud_veh_new_dashpiece_5"; + verticalFill = false; + subRegion = "4 5 98 10"; + pulseRate = "500"; + pulseThreshold = "0.3"; + }; + }; + dashboardHud.add(dashboardHud.nrgBar); + + dashboardHud.dmgBar = new HudBitmapCtrl(vDamageFrame) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "342 30"; + extent = "118 19"; + minExtent = "8 8"; + visible = "1"; + bitmap = "gui/hud_veh_new_dashpiece_4"; + flipVertical = true; + opacity = "0.8"; + + new HudDamage(vDamageBar) { + profile = "GuiDefaultProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "0 0"; + extent = "118 19"; + minExtent = "8 8"; + visible = "1"; + fillColor = "0.000000 1.0000 0.000000 0.800000"; + frameColor = "0.000000 1.000000 0.000000 0.000000"; + bitmap = "gui/hud_veh_new_dashpiece_4"; + verticalFill = false; + displayMounted = true; + opacity = "0.8"; + subRegion = "18 5 97 10"; + pulseRate = "500"; + pulseThreshold = "0.3"; + }; + }; + dashboardHud.add(dashboardHud.dmgBar); + } + // passenger slot "dots" + vOverheadHud.passengerHud = new GuiControl(vPassengerHud) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "0 0"; + extent = "101 101"; + minExtent = "8 8"; + visible = "1"; + setFirstResponder = "0"; + modal = "1"; + helpTag = "0"; + + new GuiBitmapCtrl(vPassenger0Slot) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "59 65"; + extent = "10 10"; + minExtent = "3 3"; + visible = "0"; + setFirstResponder = "0"; + modal = "1"; + bitmap = "gui/hud_veh_seatdot"; + wrap = "0"; + }; + new GuiBitmapCtrl(vPassenger1Slot) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "59 84"; + extent = "10 10"; + minExtent = "3 3"; + visible = "0"; + setFirstResponder = "0"; + modal = "1"; + bitmap = "gui/hud_veh_seatdot"; + wrap = "0"; + }; + new GuiBitmapCtrl(vPassenger2Slot) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "38 29"; + extent = "10 10"; + minExtent = "3 3"; + visible = "0"; + setFirstResponder = "0"; + modal = "1"; + bitmap = "gui/hud_veh_seatdot"; + wrap = "0"; + }; + new GuiBitmapCtrl(vPassenger3Slot) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "38 50"; + extent = "10 10"; + minExtent = "3 3"; + visible = "0"; + setFirstResponder = "0"; + modal = "1"; + bitmap = "gui/hud_veh_seatdot"; + wrap = "0"; + }; + new GuiBitmapCtrl(vPassenger4Slot) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "80 50"; + extent = "10 10"; + minExtent = "3 3"; + visible = "0"; + setFirstResponder = "0"; + modal = "1"; + bitmap = "gui/hud_veh_seatdot"; + wrap = "0"; + }; + new GuiBitmapCtrl(vPassenger5Slot) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "80 29"; + extent = "10 10"; + minExtent = "3 3"; + visible = "0"; + setFirstResponder = "0"; + modal = "1"; + bitmap = "gui/hud_veh_seatdot"; + wrap = "0"; + }; + }; + vOverheadHud.add(vOverheadHud.passengerHud); + + case "Assault" : + if(%node == 1) + { + // turreteer hud + dashboardHud.tHud = new GuiControl(turreteerHud) { + profile = "GuiDefaultProfile"; + horizSizing = "center"; + vertSizing = "top"; + position = "225 70"; + extent = "240 50"; + minExtent = "8 8"; + visible = "1"; + + new HudBitmapCtrl(vWeap1Hilite) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "bottom"; + position = "40 11"; + extent = "80 44"; + minExtent = "8 8"; + visible = "1"; + bitmap = "gui/hud_veh_new_hilite_left"; + opacity = "0.4"; + }; + new HudBitmapCtrl(vWeap2Hilite) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "bottom"; + position = "118 11"; + extent = "80 44"; + minExtent = "8 8"; + visible = "0"; + bitmap = "gui/hud_veh_new_hilite_right"; + opacity = "0.4"; + }; + + new HudBitmapCtrl(turreteerFrame) { + profile = "GuiDashBoxProfile"; + horizSizing = "center"; + vertSizing = "bottom"; + position = "20 8"; + extent = "152 36"; + minExtent = "8 8"; + visible = "1"; + bitmap = "gui/hud_veh_new_tankgunner_dash"; + opacity = "0.8"; + + new HudBitmapCtrl(vWeaponOne) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "bottom"; + position = "25 8"; + extent = "25 25"; + minExtent = "8 8"; + visible = "1"; + bitmap = "gui/hud_chaingun"; + }; + + new HudBitmapCtrl(vWeaponTwo) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "bottom"; + position = "99 8"; + extent = "25 25"; + minExtent = "8 8"; + visible = "1"; + bitmap = "gui/hud_mortor"; + }; + }; + }; + dashboardHud.add(dashboardHud.tHud); + + dashboardHud.nrgBar = new HudBitmapCtrl(vEnergyFrame) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "134 95"; + extent = "118 19"; + minExtent = "8 8"; + visible = "1"; + flipVertical = true; + bitmap = "gui/hud_veh_new_dashpiece_5"; + opacity = "0.8"; + + new HudEnergy(vEnergyBar) { + profile = "GuiDefaultProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "0 0"; + extent = "118 19"; + minExtent = "8 8"; + visible = "1"; + fillColor = "0.353000 0.373000 0.933000 0.800000"; + frameColor = "0.000000 1.000000 0.000000 1.000000"; + autoCenter = "0"; + autoResize = "0"; + displayMounted = true; + bitmap = "gui/hud_veh_new_dashpiece_5"; + verticalFill = false; + subRegion = "4 5 98 5"; + pulseRate = "500"; + pulseThreshold = "0.3"; + //modColor = "1.000000 0.500000 0.000000 1.000000"; + }; + new HudCapacitor(vCapBar) { + profile = "GuiDefaultProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "0 8"; + extent = "118 8"; + minExtent = "8 8"; + visible = "1"; + fillColor = "1.000 0.729 0.301 0.800000"; + frameColor = "0.000000 1.000000 0.000000 1.000000"; + autoCenter = "0"; + autoResize = "0"; + displayMounted = true; + bitmap = "gui/hud_veh_new_dashpiece_5"; + verticalFill = false; + subRegion = "4 5 98 5"; + pulseRate = "500"; + pulseThreshold = "0.3"; + //modColor = "1.000000 0.500000 0.000000 1.000000"; + }; + }; + dashboardHud.add(dashboardHud.nrgBar); + + dashboardHud.dmgBar = new HudBitmapCtrl(vDamageFrame) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "390 95"; + extent = "118 19"; + minExtent = "8 8"; + visible = "1"; + flipVertical = true; + bitmap = "gui/hud_veh_new_dashpiece_4"; + opacity = "0.8"; + + new HudDamage(vDamageBar) { + profile = "GuiDefaultProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "0 0"; + extent = "118 19"; + minExtent = "8 8"; + visible = "1"; + fillColor = "0.000000 1.0000 0.000000 0.800000"; + frameColor = "0.000000 1.000000 0.000000 0.000000"; + bitmap = "gui/hud_veh_new_dashpiece_4"; + verticalFill = false; + displayMounted = true; + opacity = "0.8"; + subRegion = "18 5 97 10"; + pulseRate = "500"; + pulseThreshold = "0.3"; + //modColor = "1.000000 0.500000 0.000000 1.000000"; + }; + }; + dashboardHud.add(dashboardHud.dmgBar); + + $numVWeapons = 2; + // add tank chaingun reticle + reticleHud.setBitmap("gui/hud_ret_tankchaingun"); + reticleFrameHud.setVisible(false); + } + else + { + // node 0 == driver + vOverheadHud.setBitmap("gui/hud_veh_icon_assault"); + // passenger slot "dots" + vOverheadHud.passengerHud = new GuiControl(vPassengerHud) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "0 0"; + extent = "101 101"; + minExtent = "8 8"; + visible = "1"; + + new GuiBitmapCtrl(vPassenger0Slot) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "64 30"; + extent = "10 10"; + minExtent = "3 3"; + visible = "0"; + bitmap = "gui/hud_veh_seatdot"; + }; + new GuiBitmapCtrl(vPassenger1Slot) { + profile = "GuiDashBoxProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "53 53"; + extent = "10 10"; + minExtent = "3 3"; + visible = "0"; + bitmap = "gui/hud_veh_seatdot"; + }; + }; + vOverheadHud.add(vOverheadHud.passengerHud); + } + + case "Hoverbike" : + vOverheadHud.setBitmap("gui/hud_veh_icon_hoverbike"); + + case "MPB" : + vOverheadHud.setBitmap("gui/hud_veh_icon_mpb"); + + } + if(%node == 0) + vDiagramHud.setVisible(true); + else + if(isObject(vDiagramHud)) + vDiagramHud.setVisible(false); +} + +function GuiControl::updateAltitude(%this) +{ + %alt = getControlObjectAltitude(); + vAltitudeText.setValue(%alt); + %this.altitudeCheck = %this.schedule(500, "updateAltitude"); +} + +function GuiControl::updateSpeed(%this) +{ + %vel = getControlObjectSpeed(); + // convert from m/s to km/h + %cVel = mFloor(%vel * 3.6); // m/s * (3600/1000) = km/h + vSpeedText.setValue(%cVel); + %this.speedCheck = %this.schedule(500, "updateSpeed"); +} + +//function clientCmdShowVehicleWeapons(%vehicleType) +//{ + // all vehicle weapons are energy based; a -1 displays an infinity symbol + // for that weapon's ammo amount + //switch$ (%vehicleType) + //{ + // case "ScoutFlyer": + // // blaster + // vWeaponsBox.addWeapon(0, -1); + // case "BomberFlyer": + // // plasma, bomb and targeting laser + // vWeaponsBox.addWeapon(1, -1); + // vWeaponsBox.addWeapon(3, -1); + // vWeaponsBox.addWeapon(4, -1); + // case "AssaultVehicle": + // vWeaponsBox.addWeapon(1, -1); + // vWeaponsBox.addWeapon(3, -1); + //} + //vWeaponsBox.setVisible(true); +//} + +// if set, then static shapes with data member 'noIndividualDamage' set will +// not display their damage bars +function clientCmdProtectingStaticObjects(%val) +{ + NavHud.protectedStatics = %val; +} + +function clientCmdCheckPassengers(%pString) +{ + // since each slot is represented by a "1" or a "0" followed by a space, the length + // of the string divided by 2 is equal to the number of slots in the vehicle + %numSlots = strlen(%pString) / 2; + for(%i = 0; %i < %numSlots; %i++) + { + %pass = "vPassenger" @ %i @ "Slot"; + if(isObject(%pass)) + if(getWord(%pString, %i) $= "1") + %pass.setVisible(true); + else + %pass.setVisible(false); + } +} + +function clientCmdShowPassenger(%slot, %full) +{ + %dotNum = "vPassenger" @ %slot @ "Slot"; + if(isObject(%dotNum)) + %dotNum.setVisible(%full); +} + +function clientCmdClearPassengers() +{ + for(%i = 1; %i < 6; %i++) + { + %pass = "vPassenger" @ %i @ "Slot"; + %pass.setVisible(false); + } +} + +addMessageCallback( 'MsgMissionDropInfo', handleDropInfoMessage ); +addMessageCallback( 'MsgTeamList', handleTeamListMessage ); +addMessageCallback( 'LeaveMissionArea', HandleLeaveMissionAreaAlarmMessage ); +addMessageCallback( 'EnterMissionArea', HandleEnterMissionAreaAlarmMessage ); +addMessageCallback( 'msgBountyStreakBonus', HandleBountyStreakMessage ); +addMessageCallback( 'onClientKicked', handleIveBeenKicked ); +addMessageCallback( 'onClientBanned', handleIveBeenBanned ); +addMessageCallback( 'msgDeploySensorRed', clientDeploySensorRed ); +addMessageCallback( 'msgDeploySensorGrn', clientDeploySensorGrn ); +addMessageCallback( 'msgDeploySensorOff', clientDeploySensorOff ); +addMessageCallback( 'msgPackIconOff', clientPackIconOff ); +addMessageCallback( 'MsgForceObserver', HandleForceObserver ); +addMessageCallback( 'MsgPlayerMuted', handlePlayerMuted ); + +//------------------------------------------------------------------------------ +// Siege-specific callbacks: +addMessageCallback( 'MsgSiegeHalftime', handleSiegeHalftimeMessage ); +addMessageCallback( 'MsgSiegeResult', handleSiegeResultMessage ); +addMessageCallback( 'MsgSiegeAddLine', handleSiegeLineMessage ); +//------------------------------------------------------------------------------ + +function HandleForceObserver( %msgType, %msgString ) +{ + +} + +function handleIveBeenBanned(%msgType, %msgString) +{ + DisconnectedCleanup(); +} + +function handleIveBeenKicked(%msgType, %msgString) +{ + DisconnectedCleanup(); +} + +function clientDeploySensorRed() +{ + deploySensor.color = "255 0 0"; + deploySensor.setVisible(true); +} + +function clientDeploySensorGrn() +{ + deploySensor.color = "0 255 0"; + deploySensor.setVisible(true); +} + +function clientDeploySensorOff() +{ + deploySensor.setVisible(false); +} + +function clientPackIconOff() +{ + backpackIcon.setBitmap(""); + backpackFrame.setVisible(false); + backpackText.setValue(""); + backpackText.setVisible(false); + backpackFrame.pack = false; +} + +function HandleBountyStreakMessage(%msgType, %msgString, %client, %streak, %award) +{ + %delay = alxGetWaveLen("fx/misc/bounty_bonus.wav"); + %overlap = 0.50; + + alxPlay(BountyBellSound, 0, 0, 0); //first bell + for (%loop = 1; %loop < %award; %loop++) //any repetitions, overlapped. + schedule((%delay * %loop) * %overlap, 0, "alxPlay", BountyBellSound, 0, 0, 0); +} + +function HandleLeaveMissionAreaAlarmMessage(%msgType, %msgString) +{ + //Tinman - sounds are now sent by the individual game script + //if(ServerConnection.OutOfBoundsHandle $= "") + // ServerConnection.OutOfBoundsHandle = alxPlay(OutOfBoundsSound, 0, 0, 0); +} + +function HandleEnterMissionAreaAlarmMessage(%msgType, %msgString) +{ + //Tinman - sounds are now sent by the individual game script + //if(ServerConnection.OutOfBoundsHandle !$= "") + // alxStop(ServerConnection.OutOfBoundsHandle); + // + //ServerConnection.OutOfBoundsHandle = ""; +} + +function handleDropInfoMessage( %msgType, %msgString, %map, %gameType, %serverName ) +{ + $clServerName = %serverName; + $clMissionName = %map; + $clMissionType = %gameType; +} + +function handleTeamListMessage( %msgType, %msgString, %teamCount, %teamList ) +{ + // Save off the team names: + $clTeamCount = %teamCount; + for ( %i = 0; %i < %teamCount; %i++ ) + $clTeamScore[%i + 1, 0] = getRecord( %teamList, %i ); + + // Initialize the lobby: + LobbyPlayerList.initColumns(); +} + +//---------------------------------------------------------------------------- + +function clientCmdStartEffect( %effect ) +{ + // Put in iterations + StartEffect( %effect ); +} + +function clientCmdStopEffect( %effect ) +{ + StopEffect( %effect ); +} + +function clientCmdPickTeam() +{ + +} + +function clientCmdMissionStartPhase1(%seq, %missionName, %musicTrack) +{ + echo( "got client StartPhase1..." ); + + // Reset the loading progress controls: + LoadingProgress.setValue( 0 ); + DB_LoadingProgress.setValue( 0 ); + LoadingProgressTxt.setValue( "LOADING MISSION" ); + DB_LoadingProgressTxt.setValue( "LOADING MISSION" ); + + clientCmdPlayMusic(%musicTrack); + commandToServer('MissionStartPhase1Done', %seq); + clientCmdResetCommandMap(); +} + +function clientCmdMissionStartPhase2(%seq) { + $ConstructionServerPretext = ""; + $ConstructionServerVersion = ""; + $ConstructionServerCredits = ""; + $ConstructionServerQVer = ""; + $ConstructionServerString = ""; + commandToServer('ConstructionQueryServer'); + commandToServer('ConstructionRegisterClient',"2"); + // clean some stuff up. + MessageHud.close(); + purgeResources(); + if (!$pref::NoClearConsole) + cls(); + commandToServer('MissionStartPhase2Done', %seq); +} + +function clientCmdQueryServerReply(%pretext,%version,%credits,%qVer) { + $ConstructionServerPretext = %pretext; + $ConstructionServerVersion = %version; + $ConstructionServerCredits = %credits; + $ConstructionServerQVer = %qVer; + $ConstructionServerString = %pretext SPC %version @ " - " @ %credits; + echo($ConstructionServerString @ " - (" @ %qVer @ ")"); +} + +function clientCmdMissionStartPhase3(%seq, %missionName) +{ + $MSeq = %seq; + + //Reset Inventory Hud... + if($Hud['inventoryScreen'] !$= "") + { + %favList = $Hud['inventoryScreen'].data[0, 1].type TAB $Hud['inventoryScreen'].data[0, 1].getValue(); + for ( %i = 1; %i < $Hud['inventoryScreen'].count; %i++ ) + if($Hud['inventoryScreen'].data[%i, 1].getValue() $= invalid) + %favList = %favList TAB $Hud['inventoryScreen'].data[%i, 1].type TAB "EMPTY"; + else + %favList = %favList TAB $Hud['inventoryScreen'].data[%i, 1].type TAB $Hud['inventoryScreen'].data[%i, 1].getValue(); + commandToServer( 'setClientFav', %favList ); + } + else + commandToServer( 'setClientFav', $pref::Favorite[$pref::FavCurrentSelect]); + + // needed? + $MissionName = %missionName; + //commandToServer( 'getScores' ); + + // only show dialog if actually lights + if(lightScene("sceneLightingComplete", $LaunchMode $= "SceneLight" ? "forceWritable" : "")) + { + error("beginning SceneLighting...."); + schedule(1, 0, "updateLightingProgress"); + $lightingMission = true; + LoadingProgress.setValue( 0 ); + DB_LoadingProgress.setValue( 0 ); + LoadingProgressTxt.setValue( "LIGHTING MISSION" ); + DB_LoadingProgressTxt.setValue( "LIGHTING MISSION" ); + $missionLightStarted = true; + Canvas.repaint(); + } +} + +function clientCmdMissionEnd(%seq) +{ + alxStopAll(); + // disable mission lighting if it's going (since the interiors will be gone in a sec) + $lightingMission = false; + $sceneLighting::terminateLighting = true; +} + +function clientCmdSetPowerAudioProfiles(%up, %down) +{ + setPowerAudioProfiles(%up, %down); +} + +function ghostAlwaysStarted(%ghostCount) +{ + echo( "starting to ghost " @ %ghostCount @ " server objects...."); + + LoadingProgress.setValue( 0 ); + DB_LoadingProgress.setValue( 0 ); + LoadingProgressTxt.setValue( "LOADING OBJECTS" ); + DB_LoadingProgressTxt.setValue( "LOADING OBJECTS" ); + Canvas.repaint(); + $ghostCount = %ghostCount; + $ghostsRecvd = 0; +} + +function ghostAlwaysObjectReceived() +{ + $ghostsRecvd++; + %pct = $ghostsRecvd / $ghostCount; + LoadingProgress.setValue( %pct ); + DB_LoadingProgress.setValue( %pct ); + Canvas.repaint(); +} + +function updateLightingProgress() +{ + if( $SceneLighting::lightingProgress == 0) + { + if($sceneLightStarted) + { + $sceneLightStarted = false; + } + else + $SceneLighting::lightingProgress = 1; + } + + LoadingProgress.setValue( $SceneLighting::lightingProgress ); + DB_LoadingProgress.setValue( $SceneLighting::lightingProgress ); + if($lightingMission) + $lightingProgressThread = schedule(1, 0, "updateLightingProgress"); +} + +function sceneLightingComplete() +{ + LoadingProgress.setValue( 1 ); + DB_LoadingProgress.setValue( 1 ); + + echo("Scenelighting done..."); + $lightingMission = false; + + cleanUpHuds(); + + if($LaunchMode $= "SceneLight") + { + quit(); + return; + } + + clientCmdResetHud(); + commandToServer('SetVoiceInfo', $pref::Audio::voiceChannels, $pref::Audio::decodingMask, $pref::Audio::encodingLevel); + commandToServer('EnableVehicleTeleport', $pref::Vehicle::pilotTeleport ); + commandToServer('MissionStartPhase3Done', $MSeq); +} + +function clientCmdSetVoiceInfo(%channels, %decodingMask, %encodingLevel) +{ + $Audio::serverChannels = %channels; + $Audio::serverDecodingMask = %decodingMask; + $Audio::serverEncodingLevel = %encodingLevel; +} + +function ClientReceivedDataBlock(%index, %total) +{ + %pct = %index / %total; + LoadingProgress.setValue( %pct ); + LoadingProgress.setValue( %pct ); + Canvas.repaint(); +} + +function GameConnection::onTargetLocked( %con, %state ) +{ + if( %state $= "true" ) + { + if( !%con.targetTone ) + %con.targetTone = alxPlay( "sLockedTone", 0, 0, 0 ); + } + else + { + if( %con.targetTone $= "" ) + return; + + if( %con.targetTone ) + alxStop( %con.targetTone ); + + %con.targetTone = ""; + } +} + +function GameConnection::onTrackingTarget( %con, %state ) +{ + if( %state $= "true" ) + { + if( !%con.trackingTargetTone ) + %con.trackingTargetTone = alxPlay( "sSearchingTone", 0, 0, 0 ); + } + else + { + if( %con.trackingTargetTone $= "" ) + return; + + if( %con.trackingTargetTone ) + alxStop( %con.trackingTargetTone ); + + %con.TrackingTargetTone = ""; + } +} + +function GameConnection::onLockWarning( %con, %state ) +{ + if( %state $= "true" ) + { + if( !%con.lockWarningTone ) + %con.lockWarningTone = alxPlay( "sMissileLockWarningTone", 0, 0, 0 ); + + } + else + { + if( %con.lockWarningTone $= "" ) + return; + + if( %con.lockWarningTone ) + alxStop( %con.lockWarningTone ); + + %con.lockWarningTone = ""; + } +} + +function GameConnection::onHomeWarning( %con, %state ) +{ + if( %state $= "true" ) + { + if( !%con.homeWarningTone ) + %con.homeWarningTone = alxPlay( "sMissileHomingWarningTone", 0, 0, 0 ); + } + else + { + if( %con.homeWarningTone $= "" ) + return; + + if( %con.homeWarningTone ) + alxStop( %con.homeWarningTone ); + + %con.homeWarningTone = ""; + } +} + +function GameConnection::initialControlSet(%this) +{ + if ( $LaunchMode $= "InteriorView" ) + { + Canvas.setContent( InteriorPreviewGui ); + return; + } + + if( $LaunchMode $= "TSShow" ) + { + Canvas.setContent( TSShowGui ); + return; + } + + if( Canvas.getContent() != PlayGui.getId() ) + { + Canvas.setContent( PlayGui ); + Canvas.pushDialog( MainChatHud ); + CommandToServer('PlayContentSet'); + } +} + +//------------------------------------------------------------------------------ +// Siege-specific client functions: +//------------------------------------------------------------------------------ +function handleSiegeHalftimeMessage( %msgType, %msgString ) +{ + alxPlay( SiegeSwitchSides, 0, 0, 0 ); + showTaskHudDlg( false ); + SiegeHalftimeText.setText( "" ); +} + +//------------------------------------------------------------------------------ +function handleSiegeResultMessage( %msgType, %msgString, %result ) +{ + SiegeHalftimeHeaderText.setText( "" @ detag( %result ) ); +} + +//------------------------------------------------------------------------------ +function handleSiegeLineMessage( %msgType, %msgString, %line ) +{ + %text = SiegeHalftimeText.getText(); + if ( %text $= "" ) + %newText = detag( %line ); + else + %newText = %text NL detag( %line ); + SiegeHalftimeText.setText( %newText ); +} + +//------------------------------------------------------------------------------ +function clientCmdSetHalftimeClock( %time ) +{ + SiegeHalftimeClock.setTime( %time ); +} + +//------------------------------------------------------------------------------ +function SiegeHalftimeHeaderText::onResize( %this, %width, %height ) +{ + %w = firstWord( SiegeHalftimeHeader.getExtent() ); + SiegeHalftimeHeader.setExtent( %w, %height + 6 ); + %paneHeight = getWord( siegeHalftimeHud.getExtent(), 1 ); + %x = firstWord( SiegeHalftimeScroll.getPosition() ); + %y = %height + 40; + %w = firstWord( SiegeHalftimeScroll.getExtent() ); + %h = %paneHeight - %height - 59; + SiegeHalftimeScroll.resize( %x, %y, %w, %h ); +} + +function reLightMission() { + if ($SceneLighting::lightingProgress == 0 || $SceneLighting::lightingProgress == 1) + lightScene("",forceAlways); +} + +function clientCmdReLightMission() { + if (!$pref::disallowRelight) + reLightMission(); +} diff --git a/scripts/controlDefaults.cs b/scripts/controlDefaults.cs new file mode 100644 index 0000000..e873e18 --- /dev/null +++ b/scripts/controlDefaults.cs @@ -0,0 +1,1606 @@ +if ( isObject( moveMap ) ) + moveMap.delete(); +new ActionMap(moveMap); + +//------------------------------------------------------------------------------ +// Utility remap functions: +//------------------------------------------------------------------------------ +function ActionMap::copyBind( %this, %otherMap, %command ) +{ + if ( !isObject( %otherMap ) ) + { + error( "ActionMap::copyBind - \"" @ %otherMap @ "\" is not an object!" ); + return; + } + + %bind = %otherMap.getBinding( %command ); + if ( %bind !$= "" ) + { + %device = getField( %bind, 0 ); + %action = getField( %bind, 1 ); + %flags = %otherMap.isInverted( %device, %action ) ? "SDI" : "SD"; + %deadZone = %otherMap.getDeadZone( %device, %action ); + %scale = %otherMap.getScale( %device, %action ); + %this.bind( %device, %action, %flags, %deadZone, %scale, %command ); + } +} + +//------------------------------------------------------------------------------ +function ActionMap::blockBind( %this, %otherMap, %command ) +{ + if ( !isObject( %otherMap ) ) + { + error( "ActionMap::copyBind - \"" @ %otherMap @ "\" is not an object!" ); + return; + } + + %bind = %otherMap.getBinding( %command ); + if ( %bind !$= "" ) + %this.bind( getField( %bind, 0 ), getField( %bind, 1 ), "" ); +} + +//------------------------------------------------------------------------------ +// NON-REMAPPABLE BINDS: +function escapeFromGame() +{ + if(TaskHudDlg.isVisible()) + showTaskHudDlg(false); + + if ( $currentMissionType $= "SinglePlayer" ) + Canvas.pushDialog( SinglePlayerEscapeDlg ); + else + Canvas.setContent( LobbyGui ); +} + +function toggleEditor(%make) +{ + //editor should not be available in the demo version + if (isDemo()) + return; + + if(%make) + { + if(Canvas.getContent() == Editor.getId()) + Editor.close(); + else + Editor.open(); + } +} + +moveMap.bindCmd( keyboard, "escape", "", "escapeFromGame();" ); +moveMap.bind( keyboard, "alt e", toggleEditor ); + +//------------------------------------------------------------------------------ +$movementSpeed = 1; +function setSpeed(%speed) +{ + if(%speed) + $movementSpeed = %speed; +} + +function moveleft(%val) +{ + $mvLeftAction = %val; +} + +function moveright(%val) +{ + $mvRightAction = %val; +} + +function moveforward(%val) +{ + $mvForwardAction = %val; +} + +function movebackward(%val) +{ + $mvBackwardAction = %val; +} + +function moveup(%val) +{ + $mvUpAction = %val; +} + +function movedown(%val) +{ + $mvDownAction = %val; +} + +function turnLeft( %val ) +{ + $mvYawRightSpeed = %val ? $pref::Input::KeyboardTurnSpeed : 0; +} + +function turnRight( %val ) +{ + $mvYawLeftSpeed = %val ? $pref::Input::KeyboardTurnSpeed : 0; +} + +function panUp( %val ) +{ + $mvPitchDownSpeed = %val ? $pref::Input::KeyboardTurnSpeed : 0; +} + +function panDown( %val ) +{ + $mvPitchUpSpeed = %val ? $pref::Input::KeyboardTurnSpeed : 0; +} + +// based on a default camera fov of 90' +function getMouseAdjustAmount(%val) +{ + return(%val * ($cameraFov / 90) * 0.01); +} + +function yaw(%val) +{ + $mvYaw += getMouseAdjustAmount(%val); +} + +function pitch(%val) +{ + $mvPitch += getMouseAdjustAmount(%val); +} + +moveMap.bind( keyboard, s, moveleft ); +moveMap.bind( keyboard, f, moveright ); +moveMap.bind( keyboard, e, moveforward ); +moveMap.bind( keyboard, d, movebackward ); + +function toggleDepth(%val) +{ + if (%val) { + $testDepth = !$testDepth; + } +} + +function snLine(%val) { if(%val) snapLine(); } +function snToggle(%val) { if(%val) snapToggle(); } + +moveMap.bind( mouse, xaxis, yaw ); +moveMap.bind( mouse, yaxis, pitch ); +moveMap.bind( keyboard, space, jump ); +moveMap.bind( mouse, button0, mouseFire ); +moveMap.bind( mouse, button1, mouseJet ); +//moveMap.bind( keyboard, "shift a", altTrigger ); + +//------------------------------------------------------------------------------ +// MESSAGE HUD FUNCTIONS: +function pageMessageHudUp( %val ) +{ + if ( %val ) + pageUpMessageHud(); +} + +function pageMessageHudDown( %val ) +{ + if ( %val ) + pageDownMessageHud(); +} + +moveMap.bind( keyboard, "pageUp", pageMessageHudUp ); +moveMap.bind( keyboard, "pageDown", pageMessageHudDown ); + +//------------------------------------------------------------------------------ +function voiceCapture( %val ) +{ + if ( %val ) + voiceCapStart(); + else + voiceCapStop(); +} + +moveMap.bind(keyboard, x, voiceCapture); + +//------------------------------------------------------------------------------ +// WEAPON CYCLING FUNCTIONS: +function prevWeapon( %val ) +{ + if ( %val ) + commandToServer( 'cycleWeapon', "prev" ); +} + +function nextWeapon( %val ) +{ + if ( %val ) + commandToServer( 'cycleWeapon', "next" ); +} + +function cycleWeaponAxis( %val ) +{ + if ( %val < 0 ) + commandToServer( 'cycleWeapon', "next" ); + else + commandToServer( 'cycleWeapon', "prev" ); +} + +function cycleNextWeaponOnly( %val ) +{ + if ( %val < 0 ) + commandToServer( 'cycleWeapon', "next" ); +} + +moveMap.bind( keyboard, "shift w", prevWeapon ); +moveMap.bind( keyboard, w, nextWeapon ); +moveMap.bind( mouse, zaxis, cycleWeaponAxis ); + +function toggleFreeLook( %val ) +{ + if ( %val ) + $mvFreeLook = true; + else + $mvFreeLook = false; +} + +function useRepairKit( %val ) +{ + if ( %val ) + use( RepairKit ); +} + +function useBackPack( %val ) +{ + if ( %val ) + commandToServer( 'startUseBackpack', BackPack ); + else + commandToServer( 'endUseBackpack', BackPack ); +} + +function ServerCmdStartUseBackpack( %client, %data ) +{ + %client.deployPack = false; + %client.getControlObject().use( %data ); +} + +function ServerCmdEndUseBackpack( %client ) +{ + %client.deployPack = true; +} + +moveMap.bind( keyboard, z, toggleFreeLook ); +moveMap.bind( keyboard, q, useRepairKit ); +moveMap.bind( keyboard, r, useBackpack ); + +//------------------------------------------------------------------------------ +// WEAPON SLOT SELECTION FUNCTIONS: +function useFirstWeaponSlot( %val ) +{ + if ( %val ) + commandToServer( 'selectWeaponSlot', 0 ); +} + +function useSecondWeaponSlot( %val ) +{ + if ( %val ) + commandToServer( 'selectWeaponSlot', 1 ); +} + +function useThirdWeaponSlot( %val ) +{ + if ( %val ) + commandToServer( 'selectWeaponSlot', 2 ); +} + +function useFourthWeaponSlot( %val ) +{ + if ( %val ) + commandToServer( 'selectWeaponSlot', 3 ); +} + +function useFifthWeaponSlot( %val ) +{ + if ( %val ) + commandToServer( 'selectWeaponSlot', 4 ); +} + +function useSixthWeaponSlot( %val ) +{ + if ( %val ) + commandToServer( 'selectWeaponSlot', 5 ); +} + +moveMap.bind( keyboard, "1", useFirstWeaponSlot ); +moveMap.bind( keyboard, "2", useSecondWeaponSlot ); +moveMap.bind( keyboard, "3", useThirdWeaponSlot ); +moveMap.bind( keyboard, "4", useFourthWeaponSlot ); +moveMap.bind( keyboard, "5", useFifthWeaponSlot ); +moveMap.bind( keyboard, "6", useSixthWeaponSlot ); + +//------------------------------------------------------------------------------ +// DIRECT WEAPON SELECTION FUNCTIONS: +function useBlaster( %val ) +{ + if ( %val ) + use( Blaster ); +} + +function usePlasma( %val ) +{ + if ( %val ) + use( Plasma ); +} + +function useChaingun( %val ) +{ + if ( %val ) + use( Chaingun ); +} + +function useDisc( %val ) +{ + if ( %val ) + use( Disc ); +} + +function useGrenadeLauncher( %val ) +{ + if ( %val ) + use( GrenadeLauncher ); +} + +function useSniperRifle( %val ) +{ + if ( %val ) + use( SniperRifle ); +} + +function useELFGun( %val ) +{ + if ( %val ) + use( ELFGun ); +} + +function useMortar( %val ) +{ + if ( %val ) + use( Mortar ); +} + +function useMissileLauncher( %val ) +{ + if ( %val ) + use( MissileLauncher ); +} + +function useTargetingLaser( %val ) +{ + if ( %val ) + use( TargetingLaser ); +} + +function useShockLance( %val ) +{ + if ( %val ) + use( ShockLance ); +} + +function useConstructionTool(%val) +{ +if (%val) + use ( ConstructionTool ); +} + +function throwGrenade( %val ) +{ + if ( %val ) + commandToServer( 'startThrowCount' ); + else + commandToServer( 'endThrowCount' ); + $mvTriggerCount4 += $mvTriggerCount4 & 1 == %val ? 2 : 1; +} + +function placeMine( %val ) +{ + if ( %val ) + commandToServer( 'startThrowCount' ); + else + commandToServer( 'endThrowCount' ); + $mvTriggerCount5 += $mvTriggerCount5 & 1 == %val ? 2 : 1; +} + +function placeBeacon( %val ) +{ + if ( %val ) + use( Beacon); +} + +moveMap.bind( keyboard, g, throwGrenade ); +moveMap.bind( keyboard, b, placeMine ); +moveMap.bind( keyboard, h, placeBeacon ); +moveMap.bind( keyboard, l, useTargetingLaser ); + +function throwWeapon( %val ) +{ + if ( %val ) + commandToServer( 'throwWeapon' ); +} + +function throwPack( %val ) +{ + if ( %val ) + commandToServer('throwPack'); +} + +function throwFlag( %val ) +{ + // TR2: Allow variable strength passes + if (objectiveHud.gameType $= "TR2Game") + { + if ( %val ) + { + doFlagGauge(%val); + commandToServer( 'startFlagThrowCount' ); + + // Schedule to remove the HUD in 3 seconds. + $TR2HideGaugeThread = schedule(2500, 0, "hideFlagGauge"); + } + else + { + cancel($TR2HideGaugeThread); + commandToServer( 'endFlagThrowCount' ); + + // If we're still trying to throw it, throw it. Don't bother trying + // to remove this to get max toss flag throws...it doesn't work. + if ($TR2FGaugeThread > 0) + commandToServer('throwFlag'); + doFlagGauge(%val); + } + + // What's this global for? + //$mvTriggerCount6 += $mvTriggerCount6 & 1 == %val ? 2 : 1; + } + else if ( %val ) + commandToServer('throwFlag'); +} + +moveMap.bind( keyboard, "ctrl w", throwWeapon ); +moveMap.bind( keyboard, "ctrl r", throwPack ); +moveMap.bind( keyboard, "ctrl f", throwFlag ); + +function resizeChatHud( %val ) +{ + if ( %val ) + MainChatHud.nextChatHudLen(); +} + +moveMap.bind( keyboard, "p", resizeChatHud ); + +//------------------------------------------------------------------------------ +// ZOOM FUNCTIONS: +if($pref::player::currentFOV $= "") + $pref::player::currentFOV = 45; + +function setZoomFOV(%val) +{ + if(%val) + calcZoomFOV(); +} + +function toggleZoom( %val ) +{ + if ( %val ) + { + if(ZoomHud.isVisible()) + { + cancel(ZoomHud.hideThread); + hideZoomHud(); + } + $ZoomOn = true; + setFov( $pref::player::currentFOV ); + } + else + { + $ZoomOn = false; + setFov( $pref::player::defaultFov ); + } +} + +moveMap.bind(keyboard, t, setZoomFOV); +moveMap.bind(keyboard, a, toggleZoom); + +//------------------------------------------------------------------------------ +// INVENTORY FAVORITE FUNCTIONS: +function toggleInventoryHud( %val ) +{ + if ( %val ) + toggleCursorHuds('inventoryScreen'); +} + +function selectFavorite1( %val ) +{ + if ( %val ) + loadFavorite( 0, 1 ); +} + +function selectFavorite2( %val ) +{ + if ( %val ) + loadFavorite( 1, 1 ); +} + +function selectFavorite3( %val ) +{ + if ( %val ) + loadFavorite( 2, 1 ); +} + +function selectFavorite4( %val ) +{ + if ( %val ) + loadFavorite( 3, 1 ); +} + +function selectFavorite5( %val ) +{ + if ( %val ) + loadFavorite( 4, 1 ); +} + +function selectFavorite6( %val ) +{ + if ( %val ) + loadFavorite( 5, 1 ); +} + +function selectFavorite7( %val ) +{ + if ( %val ) + loadFavorite( 6, 1 ); +} + +function selectFavorite8( %val ) +{ + if ( %val ) + loadFavorite( 7, 1 ); +} + +function selectFavorite9( %val ) +{ + if ( %val ) + loadFavorite( 8, 1 ); +} + +function selectFavorite10( %val ) +{ + if ( %val ) + loadFavorite( 9, 1 ); +} + +function selectFavorite11( %val ) +{ + if ( %val ) + loadFavorite( 10, 1 ); +} + +function selectFavorite12( %val ) +{ + if ( %val ) + loadFavorite( 11, 1 ); +} + +function selectFavorite13( %val ) +{ + if ( %val ) + loadFavorite( 12, 1 ); +} + +function selectFavorite14( %val ) +{ + if ( %val ) + loadFavorite( 13, 1 ); +} + +function selectFavorite15( %val ) +{ + if ( %val ) + loadFavorite( 14, 1 ); +} + +function selectFavorite16( %val ) +{ + if ( %val ) + loadFavorite( 15, 1 ); +} + +function selectFavorite17( %val ) +{ + if ( %val ) + loadFavorite( 16, 1 ); +} + +function selectFavorite18( %val ) +{ + if ( %val ) + loadFavorite( 17, 1 ); +} + +function selectFavorite19( %val ) +{ + if ( %val ) + loadFavorite( 18, 1 ); +} + +function selectFavorite20( %val ) +{ + if ( %val ) + loadFavorite( 19, 1 ); +} + +moveMap.bind( keyboard, numpadenter, toggleInventoryHud ); +moveMap.bind( keyboard, numpad1, selectFavorite1 ); +moveMap.bind( keyboard, numpad2, selectFavorite2 ); +moveMap.bind( keyboard, numpad3, selectFavorite3 ); +moveMap.bind( keyboard, numpad4, selectFavorite4 ); +moveMap.bind( keyboard, numpad5, selectFavorite5 ); +moveMap.bind( keyboard, numpad6, selectFavorite6 ); +moveMap.bind( keyboard, numpad7, selectFavorite7 ); +moveMap.bind( keyboard, numpad8, selectFavorite8 ); +moveMap.bind( keyboard, numpad9, selectFavorite9 ); +moveMap.bind( keyboard, numpad0, selectFavorite10 ); + +moveMap.bind( keyboard, "shift numpad1", selectFavorite11 ); +moveMap.bind( keyboard, "shift numpad2", selectFavorite12 ); +moveMap.bind( keyboard, "shift numpad3", selectFavorite13 ); +moveMap.bind( keyboard, "shift numpad4", selectFavorite14 ); +moveMap.bind( keyboard, "shift numpad5", selectFavorite15 ); +moveMap.bind( keyboard, "shift numpad6", selectFavorite16 ); +moveMap.bind( keyboard, "shift numpad7", selectFavorite17 ); +moveMap.bind( keyboard, "shift numpad8", selectFavorite18 ); +moveMap.bind( keyboard, "shift numpad9", selectFavorite19 ); +moveMap.bind( keyboard, "shift numpad0", selectFavorite20 ); + +moveMap.bind( keyboard, "ctrl numpad0", quickPackEnergyPack ); +moveMap.bind( keyboard, "ctrl numpad1", quickPackRepairPack ); +moveMap.bind( keyboard, "ctrl numpad2", quickPackShieldPack ); +moveMap.bind( keyboard, "ctrl numpad3", quickPackCloakPack ); +moveMap.bind( keyboard, "ctrl numpad4", quickPackJammerPack ); +moveMap.bind( keyboard, "ctrl numpad5", quickPackAmmoPack ); +moveMap.bind( keyboard, "ctrl numpad6", quickPackSatchelCharge ); +moveMap.bind( keyboard, "ctrl numpad7", quickPackDeployableStation ); +moveMap.bind( keyboard, "ctrl numpad8", quickPackIndoorTurret ); +moveMap.bind( keyboard, "ctrl numpad9", quickPackOutdoorTurret ); +moveMap.bind( keyboard, "ctrl numpaddivide", quickPackMotionSensor ); +moveMap.bind( keyboard, "ctrl numpadmult", quickPackPulse ); + +function quickPackRepairPack(%val) +{ + if(%val) + addQuickPackFavorite("Repair Pack"); +} + +function quickPackEnergyPack(%val) +{ + if(%val) + addQuickPackFavorite("Energy Pack"); +} + +function quickPackShieldPack(%val) +{ + if(%val) + addQuickPackFavorite("Shield Pack"); +} + +function quickPackCloakPack(%val) +{ + if(%val) + addQuickPackFavorite("Cloak Pack"); +} + +function quickPackJammerPack(%val) +{ + if(%val) + addQuickPackFavorite("Sensor Jammer Pack"); +} + +function quickPackAmmoPack(%val) +{ + if(%val) + addQuickPackFavorite("Ammunition Pack"); +} + +function quickPackSatchelCharge(%val) +{ + if(%val) + addQuickPackFavorite("Satchel Charge"); +} + +function quickPackDeployableStation(%val) +{ + if(%val) + addQuickPackFavorite("Inventory Station"); +} + +function quickPackIndoorTurret(%val) +{ + if(%val) + addQuickPackFavorite("Spider Clamp Turret"); +} + +function quickPackOutdoorTurret(%val) +{ + if(%val) + addQuickPackFavorite("Landspike Turret"); +} + +function quickPackMotionSensor(%val) +{ + if(%val) + addQuickPackFavorite("Motion Sensor Pack"); +} + +function quickPackPulse(%val) +{ + if(%val) + addQuickPackFavorite("Pulse Sensor Pack"); +} + +function quickPackMortarBarrel(%val) +{ + if(%val) + addQuickPackFavorite("Mortar Turret Barrel"); +} + +function quickPackElfBarrel(%val) +{ + if(%val) + addQuickPackFavorite("ELF Turret Barrel"); +} + +function quickPackAABarrel(%val) +{ + if(%val) + addQuickPackFavorite("AA Turret Barrel"); +} + +function quickPackPlasmaBarrel(%val) +{ + if(%val) + addQuickPackFavorite("Plasma Turret Barrel"); +} + +function quickPackMissileBarrel(%val) +{ + if(%val) + addQuickPackFavorite("Missile Turret Barrel"); +} + +function quickPackFlashGrenade(%val) +{ + if(%val) + addQuickPackFavorite("Whiteout Grenade", grenade); +} + +function quickPackConcussionGrenade(%val) +{ + if(%val) + addQuickPackFavorite("Concussion Grenade", grenade); +} + +function quickPackGrenade(%val) +{ + if(%val) + addQuickPackFavorite("Grenade", grenade); +} + +function quickPackFlareGrenade(%val) +{ + if(%val) + addQuickPackFavorite("Flare Grenade", grenade); +} + +function quickPackCameraGrenade(%val) +{ + if(%val) + addQuickPackFavorite("Deployable Camera", grenade); +} + +// Construction +function quickPackLightSupportBeam(%val) { + if (%val) + addQuickPackFavorite("Light Support Beam", dep); +} + +function quickPackLightWalkway(%val) { + if (%val) + addQuickPackFavorite("Light Walkway", dep); +} + +function quickPackLightBlastWall(%val) { + if (%val) + addQuickPackFavorite("Light Blast Wall", dep); +} + +function quickPackMediumSupportBeam(%val) { + if (%val) + addQuickPackFavorite("Medium Support Beam", dep); +} + +function quickPackMediumFloor(%val) { + if (%val) + addQuickPackFavorite("Medium Floor", dep); +} + +function quickPackInventoryStation(%val) { + if (%val) + addQuickPackFavorite("Inventory Station", dep); +} + +function quickPackLargeInventoryStation(%val) { + if (%val) + addQuickPackFavorite("Large Inventory station", dep); +} + +function quickPackGeneratorPack(%val) { + if (%val) + addQuickPackFavorite("Generator Pack", dep); +} + +function quickPackSolarPanelPack(%val) { + if (%val) + addQuickPackFavorite("Solar Panel Pack", dep); +} + +function quickPackSwitchPack(%val) { + if (%val) + addQuickPackFavorite("Switch Pack", dep); +} + +function quickPackMediumSensorPack(%val) { + if (%val) + addQuickPackFavorite("Medium Sensor Pack", dep); +} + +function quickPackLargeSensorPack(%val) { + if (%val) + addQuickPackFavorite("Large Sensor Pack", dep); +} + +function quickPackTeleportPad(%val) { + if (%val) + addQuickPackFavorite("Teleport Pad", dep); +} + +function quickPackDeployableTurretBase(%val) { + if (%val) + addQuickPackFavorite("Deployable Turret Base", dep); +} + +function quickPackEnergizer(%val) { + if (%val) + addQuickPackFavorite("Energizer", dep); +} + +function quickPackTreePack(%val) { + if (%val) + addQuickPackFavorite("Tree Pack", dep); +} + +function quickPackCratePack(%val) { + if (%val) + addQuickPackFavorite("Crate Pack", dep); +} + +function quickPackDecorationPack(%val) { + if (%val) + addQuickPackFavorite("Decoration Pack", dep); +} + +function quickPackLightPack(%val) { + if (%val) + addQuickPackFavorite("Light Pack", dep); +} + +function quickPackTripwirePack(%val) { + if (%val) + addQuickPackFavorite("Tripwire Pack", dep); +} + +function quickPackLogoProjectorPack(%val) { + if (%val) + addQuickPackFavorite("Logo Projector Pack", dep); +} + +function quickPackForceField(%val) { + if (%val) + addQuickPackFavorite("Force Field", dep); +} + +function quickPackGravityField(%val) { + if (%val) + addQuickPackFavorite("Gravity Field", dep); +} + +function quickPackJumpPad(%val) { + if (%val) + addQuickPackFavorite("Jump Pad", dep); +} + +function quickPackEscapePod(%val) { + if (%val) + addQuickPackFavorite("Escape Pod", dep); +} + +function quickPackDiscTurret(%val) { + if (%val) + addQuickPackFavorite("Disc Turret"); +} + +function quickPackLaserTurret(%val) { + if (%val) + addQuickPackFavorite("Laser Turret"); +} + +function quickPackMissileRackTurret(%val) { + if (%val) + addQuickPackFavorite("Missile Rack Turret"); +} + +function cyclePackFwd(%val) { + if (%val) + commandToServer('CyclePackSetting',1); +} + +function cyclePackBack(%val) { + if (%val) + commandToServer('CyclePackSetting',-1); +} + +function cyclePackFFwd(%val) { + if (%val) + commandToServer('CyclePackSetting',5); +} + +function cyclePackFBack(%val) { + if (%val) + commandToServer('CyclePackSetting',-5); +} + +function serverCmdCyclePackSetting(%client,%val) { + %plyr = %client.player; + if (isObject(%plyr)) + cyclePackSetting(%plyr,%val); +} + +// Emotes +function emoteSitDown(%val) { + if (%val) + commandToServer('Emote',"SitDown"); +} + +function emoteSquat(%val) { + if (%val) + commandToServer('Emote',"Squat"); +} + +function emoteJig(%val) { + if (%val) + commandToServer('Emote',"Jig"); +} + +function emoteLieDown(%val) { + if (%val) + commandToServer('Emote',"LieDown"); +} + +function emoteHeartAttack(%val) { + if (%val) + commandToServer('Emote',"HeartAttack"); +} + +function emoteSuckerPunched(%val) { + if (%val) + commandToServer('Emote',"SuckerPunched"); +} + +function serverCmdEmote(%client,%anim) { + %plyr = %client.player; + if (isObject(%plyr)) { + switch$ (%anim) { + case "SitDown": + %plyr.setActionThread("sitting",true); + case "Squat": + %plyr.setActionThread("scoutRoot",true); + case "Jig": + %plyr.setActionThread("ski",true); + case "LieDown": + %plyr.setActionThread("death9",true); + case "HeartAttack": + %plyr.setActionThread("death8",true); + case "SuckerPunched": + %plyr.setActionThread("death11",true); + } + } +} + +// End Construction + + +moveMap.bind( keyboard, tab, toggleFirstPerson ); +moveMap.bind( keyboard, u, ToggleMessageHud ); +moveMap.bind( keyboard, y, TeamMessageHud ); +moveMap.bind( keyboard, v, activateChatMenuHud ); + +function toggleCommanderMap( %val ) +{ + if ( %val ) + { + showTaskHudDlg(false); + CommanderMapGui.toggle(); + } +} + +moveMap.bind( keyboard, c, toggleCommanderMap ); +moveMap.bind( keyboard, "ctrl k", suicide ); + +function report(%val) +{ + if(%val) + commandToServer('report'); +} + +function suicide(%val) +{ + if (%val) + commandToServer('suicide'); +} + +function toggleFirstPerson(%val) +{ + if (%val) + { + $firstPerson = !$firstPerson; + hudFirstPersonToggled(); + } +} + +function toggleCamera(%val) +{ + if (%val) + commandToServer('ToggleCamera'); +} + +function dropPlayerAtCamera(%val) +{ + if (%val) + commandToServer('DropPlayerAtCamera'); +} + +function dropCameraAtPlayer(%val) +{ + if (%val) + commandToServer('dropCameraAtPlayer'); +} + +function dropPlayerAtCamera(%val) +{ + if (%val) + commandToServer('DropPlayerAtCamera'); +} + +function togglePlayerRace(%val) +{ + if (%val) + commandToServer('ToggleRace'); +} + +function togglePlayerGender(%val) +{ + if (%val) + commandToServer('ToggleGender'); +} + +function togglePlayerArmor(%val) +{ + if (%val) + commandToServer('ToggleArmor'); +} + +function jump(%val) +{ + //$mvTriggerCount2++; + $mvTriggerCount2 += (($mvTriggerCount2 & 1) == %val) ? 2 : 1; +} + +// moveMap.bind(keyboard, "alt c", playCel); +// moveMap.bind(keyboard, "alt a", toggleArmor); +// moveMap.bind(keyboard, "alt d", playDeath); + +//function playCel(%val) +//{ +// if (%val) +// commandToServer('playCel',%anim); +//} + +//function playDeath(%val) +//{ +// if (%val) +// commandToServer('playDeath',%anim); +//} + +function mouseFire(%val) +{ + $mvTriggerCount0 += (($mvTriggerCount0 & 1) == %val) ? 2 : 1; +} + +function mouseJet(%val) +{ + $mvTriggerCount3 += (($mvTriggerCount3 & 1) == %val) ? 2 : 1; +} + +function altTrigger(%val) +{ + $mvTriggerCount1 += (($mvTriggerCount1 & 1) == %val) ? 2 : 1; +} + +function testLOSTarget() +{ + ServerConnection.sendLOSTarget(); + commandToServer('TestLOS'); +} + +function serverCmdTestLOS(%client) +{ + %client.sendTargetTo(%client); + %msg = 'This is a simple test.'; + messageClient(%client, 'TestMsg', %msg); +} + +//------------------------------------------------------------------------------ +function toggleHelpGui( %val ) +{ + if ( %val ) + toggleHelpText(); +} + +function toggleScoreScreen( %val ) +{ + if ( %val ) + toggleCursorHuds('scoreScreen'); +} + +moveMap.bind( keyboard, F1, toggleHelpGui ); +moveMap.bind( keyboard, F2, toggleScoreScreen ); + +//------------------------------------------------------------------------------ +// DEMO RECORD FUNCTIONS: +function startRecordingDemo( %val ) +{ + if ( %val ) + beginDemoRecord(); +} + +function stopRecordingDemo( %val ) +{ + if ( %val ) + stopDemoRecord(); +} + +if ( !isDemo() ) +{ + moveMap.bind( keyboard, F3, startRecordingDemo ); + moveMap.bind( keyboard, F4, stopRecordingDemo ); +} + +//------------------------------------------------------------------------------ +// NAV HUD DISPLAY FUNCTIONS: +function toggleHudWaypoints(%val) +{ + if(%val) + navHud.setMarkerTypeVisible(ClientWaypoint, !navHud.isMarkerTypeVisible(ClientWaypoint)); +} + +function toggleHudMarkers(%val) +{ + if(%val) + navHud.setMarkerTypeVisible(MissionWaypoint, !navHud.isMarkerTypeVisible(MissionWaypoint)); +} + +function toggleHudTargets(%val) +{ + if(%val) + { + %visible = navHud.isMarkerTypeVisible(Target); + PlayGui.beaconsVisible = !%visible; + navHud.setMarkerTypeVisible(Target, !%visible); + } +} + +function toggleHudCommands(%val) +{ + if(%val) + { + %visible = navHud.isMarkerTypeVisible(PotentialTask); + navHud.setMarkerTypeVisible(PotentialTask, !%visible); + navHud.setMarkerTypeVisible(AssignedTask, !%visible); + } +} + +moveMap.bind( keyboard, F6, toggleHudWaypoints ); +moveMap.bind( keyboard, F7, toggleHudMarkers ); +moveMap.bind( keyboard, F8, toggleHudCommands ); +moveMap.bind( keyboard, F9, toggleHudTargets ); + +//------------------------------------------------------------------------------ +// TASK FUNCTIONS: +function fnAcceptTask( %val ) +{ + if ( %val ) + clientAcceptCurrentTask(); +} + +function fnDeclineTask( %val ) +{ + if ( %val ) + clientDeclineCurrentTask(); +} + +function fnTaskCompleted( %val ) +{ + if ( %val ) + clientTaskCompleted(); +} + +function fnResetTaskList( %val ) +{ + if ( %val ) + TaskList.reset(); +} + +// tasks +moveMap.bind( keyboard, n, toggleTaskListDlg ); +moveMap.bind( keyboard, "enter", fnAcceptTask ); +moveMap.bind( keyboard, "backspace", fnDeclineTask ); +moveMap.bind( keyboard, "shift c", fnTaskCompleted ); +moveMap.bind( keyboard, "shift x", fnResetTaskList ); + +// misc: +moveMap.bind( keyboard, "ctrl n", toggleNetDisplayHud ); + +//------------------------------------------------------------------------------ +// VOTING FUNCTIONS: +function voteYes( %val ) +{ + if ( %val ) + setPlayerVote( true ); +} + +function voteNo( %val ) +{ + if ( %val ) + setPlayerVote( false ); +} + +moveMap.bind( keyboard, insert, voteYes ); +moveMap.bind( keyboard, delete, voteNo ); + +/////////////////////// +// Observer Keys +/////////////////////// +if ( isObject( observerMap ) ) + observerMap.delete(); +new ActionMap( observerMap ); +observerMap.bind( keyboard, t, moveup ); +observerMap.bind( keyboard, b, movedown ); +observerMap.bind( keyboard, space, jump ); +observerMap.bind( mouse, button0, mouseFire ); +observerMap.bind( mouse, button1, mouseJet ); + +if(!isDemo()) +{ + observerMap.copyBind(moveMap, startRecordingDemo); + observerMap.copyBind(moveMap, stopRecordingDemo); +} + +/////////////////////// +// Vehicle Keys +/////////////////////// +function clientCmdSetWeaponryVehicleKeys() +{ + %bind = moveMap.getBinding( nextWeapon ); + passengerKeys.bind( getField( %bind, 0 ), getField( %bind, 1 ), nextVehicleWeapon ); + + %bind = moveMap.getBinding( prevWeapon ); + passengerKeys.bind( getField( %bind, 0 ), getField( %bind, 1 ), prevVehicleWeapon ); + + %bind = moveMap.getBinding( cycleWeaponAxis ); + passengerKeys.bind( getField( %bind, 0 ), getField( %bind, 1 ), cycleVehicleWeapon ); + + %bind = moveMap.getBinding( cycleNextWeaponOnly ); + passengerKeys.bind( getField( %bind, 0 ), getField( %bind, 1 ), cycleNextVehicleWeaponOnly ); + + passengerKeys.bind( keyboard, 1, useWeaponOne ); + passengerKeys.bind( keyboard, 2, useWeaponTwo ); + passengerKeys.bind( keyboard, 3, useWeaponThree ); +} + +function clientCmdSetPilotVehicleKeys() +{ + passengerKeys.copyBind( moveMap, toggleFirstPerson ); + passengerKeys.copyBind( moveMap, toggleFreeLook ); + passengerKeys.copyBind( moveMap, mouseJet ); + + // Use the InvertVehicleYAxis pref: + if ( $pref::Vehicle::InvertYAxis ) + { + %bind = moveMap.getBinding( pitch ); + %device = getField( %bind, 0 ); + %action = getField( %bind, 1 ); + %flags = moveMap.isInverted( %device, %action ) ? "SD" : "SDI"; + %deadZone = moveMap.getDeadZone( %device, %action ); + %scale = moveMap.getScale( %device, %action ); + passengerKeys.bind( %device, %action, %flags, %deadZone, %scale, pitch ); + } +} + +function clientCmdSetPassengerVehicleKeys() +{ + passengerKeys.copyBind( moveMap, toggleZoom ); + passengerKeys.copyBind( moveMap, setZoomFOV ); + passengerKeys.copyBind( moveMap, toggleScoreScreen ); +} + +function clientCmdSetDefaultVehicleKeys(%inVehicle) +{ + if ( %inVehicle ) + { + if ( isObject( passengerKeys ) ) + { + passengerKeys.pop(); + passengerKeys.delete(); + } + new ActionMap( passengerKeys ); + + // Bind all of the movement keys: + passengerKeys.copyBind( moveMap, moveleft ); + passengerKeys.copyBind( moveMap, moveright ); + passengerKeys.copyBind( moveMap, moveforward ); + passengerKeys.copyBind( moveMap, movebackward ); + passengerKeys.copyBind( moveMap, mouseFire ); + passengerKeys.copyBind( moveMap, yaw ); + passengerKeys.copyBind( moveMap, pitch ); + passengerKeys.copyBind( moveMap, turnLeft ); + passengerKeys.copyBind( moveMap, turnRight ); + passengerKeys.copyBind( moveMap, panUp ); + passengerKeys.copyBind( moveMap, panDown ); + passengerKeys.copyBind( moveMap, jump ); + passengerKeys.copyBind( moveMap, setZoomFOV ); + passengerKeys.copyBind( moveMap, toggleZoom ); + + // Copy the joystick binds as well: + passengerKeys.copyBind( moveMap, joyPitch ); + passengerKeys.copyBind( moveMap, joyYaw ); + passengerKeys.copyBind( moveMap, joystickMoveX ); + passengerKeys.copyBind( moveMap, joystickMoveY ); + + // Bind the chat keys as well: + passengerKeys.copyBind( moveMap, ToggleMessageHud ); + passengerKeys.copyBind( moveMap, TeamMessageHud ); + passengerKeys.copyBind( moveMap, resizeChatHud ); + passengerKeys.copyBind( moveMap, pageMessageHudUp ); + passengerKeys.copyBind( moveMap, pageMessageHudDown ); + passengerKeys.copyBind( moveMap, activateChatMenuHud ); + passengerKeys.copyBind( moveMap, voiceCapture ); + + // Miscellaneous other binds: + passengerKeys.copyBind( moveMap, useBackpack ); + passengerKeys.copyBind( moveMap, useRepairKit ); + passengerKeys.copyBind( moveMap, suicide ); + passengerKeys.copyBind( moveMap, voteYes ); + passengerKeys.copyBind( moveMap, voteNo ); + passengerKeys.copyBind( moveMap, toggleCommanderMap ); + passengerKeys.bindCmd( keyboard, escape, "", "escapeFromGame();" ); + passengerKeys.copyBind( moveMap, toggleHelpGui ); + passengerKeys.copyBind( moveMap, toggleScoreScreen ); + passengerKeys.copyBind( moveMap, toggleNetDisplayHud ); + + // Bind the weapon keys as well: + passengerKeys.copyBind( moveMap, nextWeapon ); + passengerKeys.copyBind( moveMap, prevWeapon ); + passengerKeys.copyBind( moveMap, cycleWeaponAxis ); + passengerKeys.copyBind( moveMap, cycleNextWeaponOnly ); + + passengerKeys.copyBind( moveMap, useFirstWeaponSlot ); + passengerKeys.copyBind( moveMap, useSecondWeaponSlot ); + passengerKeys.copyBind( moveMap, useThirdWeaponSlot ); + passengerKeys.copyBind( moveMap, useFourthWeaponSlot ); + passengerKeys.copyBind( moveMap, useFifthWeaponSlot ); + passengerKeys.copyBind( moveMap, useSixthWeaponSlot ); + + // Bind individual weapons as well: + passengerKeys.copyBind( moveMap, useBlaster ); + passengerKeys.copyBind( moveMap, usePlasma ); + passengerKeys.copyBind( moveMap, useChaingun ); + passengerKeys.copyBind( moveMap, useDisc ); + passengerKeys.copyBind( moveMap, useGrenadeLauncher ); + passengerKeys.copyBind( moveMap, useSniperRifle ); + passengerKeys.copyBind( moveMap, useELFGun ); + passengerKeys.copyBind( moveMap, useMortar ); + passengerKeys.copyBind( moveMap, useMissileLauncher ); + passengerKeys.copyBind( moveMap, useTargetingLaser ); + passengerKeys.copyBind( moveMap, useShockLance ); + passengerKeys.copyBind( moveMap, throwGrenade ); + passengerKeys.copyBind( moveMap, placeMine ); + + // Bind the command assignment/response keys as well: + passengerKeys.copyBind( moveMap, toggleTaskListDlg ); + passengerKeys.copyBind( moveMap, fnAcceptTask ); + passengerKeys.copyBind( moveMap, fnDeclineTask ); + passengerKeys.copyBind( moveMap, fnTaskCompleted ); + passengerKeys.copyBind( moveMap, fnResetTaskList ); + + // grab the demo recorder binds + passengerKeys.copyBind( moveMap, startRecordingDemo ); + passengerKeys.copyBind( moveMap, stopRecordingDemo ); + } + else if ( isObject( passengerKeys ) ) + { + passengerKeys.pop(); + passengerKeys.delete(); + } +} + +function useWeaponOne(%val) +{ + if(%val) + commandToServer('setVehicleWeapon', 1); +} + +function useWeaponTwo(%val) +{ + if(%val) + commandToServer('setVehicleWeapon', 2); +} + +function useWeaponThree(%val) +{ + if(%val) + commandToServer('setVehicleWeapon', 3); +} + +function serverCmdSetVehicleWeapon(%client, %num) +{ + %turret = %client.player.getControlObject(); + if(%turret.getDataBlock().numWeapons < %num) + return; + %turret.selectedWeapon = %num; + + //%hudNum = %turret.getDataBlock().getHudNum(%num); + //%client.setVWeaponsHudActive(%hudNum); + %client.setVWeaponsHudActive(%num); + + // set the active image on the client's obj + if(%num == 1) + %client.setObjectActiveImage(%turret, 2); + else if(%num == 2) + %client.setObjectActiveImage(%turret, 4); + else + %client.setObjectActiveImage(%turret, 6); + + // if firing then set the proper image trigger + if(%turret.fireTrigger) + { + if(%num == 1) + { + %turret.setImageTrigger(4, false); + if(%turret.getImageTrigger(6)) + { + %turret.setImageTrigger(6, false); + ShapeBaseImageData::deconstruct(%turret.getMountedImage(6), %turret); + } + %turret.setImageTrigger(2, true); + } + else if( %num == 2) + { + %turret.setImageTrigger(2, false); + if(%turret.getImageTrigger(6)) + { + %turret.setImageTrigger(6, false); + ShapeBaseImageData::deconstruct(%turret.getMountedImage(6), %turret); + } + %turret.setImageTrigger(4, true); + } + else + { + %turret.setImageTrigger(2, false); + %turret.setImageTrigger(4, false); + } + } +} + +function nextVehicleWeapon(%val) +{ + if ( %val ) + commandToServer('switchVehicleWeapon', "next"); +} + +function prevVehicleWeapon(%val) +{ + if ( %val ) + commandToServer('switchVehicleWeapon', "prev"); +} + +function cycleVehicleWeapon( %val ) +{ + if ( %val < 0 ) + commandToServer( 'switchVehicleWeapon', "next" ); + else + commandToServer( 'switchVehicleWeapon', "prev" ); +} + +function cycleNextVehicleWeaponOnly( %val ) +{ + if ( %val < 0 ) + commandToServer( 'switchVehicleWeapon', "next" ); +} + +function serverCmdSwitchVehicleWeapon(%client, %dir) +{ + %turret = %client.player.getControlObject(); + %weaponNum = %turret.selectedWeapon; + if(%dir $= "next") + { + if(%weaponNum++ > %turret.getDataBlock().numWeapons) + %weaponNum = 1; + } + else + { + if(%weaponNum-- < 1) + %weaponNum = %turret.getDataBlock().numWeapons; + } + serverCmdSetVehicleWeapon(%client, %weaponNum); +} + + +/////////////////////// +//Station +/////////////////////// +function clientCmdSetStationKeys(%inStation) +{ + if ( %inStation ) + { + if ( isObject( stationMap ) ) + { + stationMap.pop(); + stationMap.delete(); + } + new ActionMap( stationMap ); + stationMap.blockBind( moveMap, toggleInventoryHud ); + stationMap.bind( keyboard, escape, "" ); + stationMap.push(); + } + else if ( isObject( stationMap ) ) + { + stationMap.pop(); + stationMap.delete(); + } +} + +$MFDebugRenderMode = 0; +function cycleDebugRenderMode() +{ + if($MFDebugRenderMode == 0) + { + show(); + GLEnableOutline(true); + $MFDebugRenderMode = 1; + } + else if ($MFDebugRenderMode == 1) + { + GLEnableOutline(false); + setInteriorRenderMode(7); + $MFDebugRenderMode = 2; + } + else if ($MFDebugRenderMode == 2) + { + setInteriorRenderMode(0); + GLEnableOutline(false); + showTri(); + $MFDebugRenderMode = 0; + } +} + +// Since the toggle console key is remappable, put it here: +if (!isDemo()) + GlobalActionMap.bind(keyboard, "grave", toggleConsole); diff --git a/scripts/dEffects.cs b/scripts/dEffects.cs new file mode 100644 index 0000000..80bd34e --- /dev/null +++ b/scripts/dEffects.cs @@ -0,0 +1,284 @@ +// Deploy effects + +datablock AudioProfile(DrillLinkSound) +{ + filename = "fx/misc/mine.deploy.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(SingeLinkSound) +{ + filename = "fx/weapons/chaingun_off.wav"; // "fx/weapons/grenade_camera_activate.wav"; + description = AudioClose3d; + preload = true; +}; + + +datablock AudioProfile(BoltLinkSound) +{ + filename = "fx/misc/health_patch.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(ClickLinkSound) +{ + filename = "fx/misc/health_patch.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(SingeSound) +{ + filename = "fx/weapons/ElF_hit.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(LargeLinkeSound) +{ + filename = "fx/weapons/grenade_explode_UW.wav"; + description = AudioClose3d; + preload = true; +}; + + +datablock LinearProjectileData(FastSingeProjectile) { + className = "LinearProjectileData"; + projectileShapeName = "turret_muzzlepoint.dts"; + emitterDelay = "-1"; + velInheritFactor = "0"; + directDamage = "0"; + hasDamageRadius = "0"; + indirectDamage = "0"; + damageRadius = "0"; + radiusDamageType = "0"; + kickBackStrength = "0"; + baseEmitter = "ELFSparksEmitter"; + hasLight = "0"; + lightRadius = "20"; + lightColor = "1.000000 1.000000 1.000000 1.000000"; + hasLightUnderwaterColor = "0"; + underWaterLightColor = "1.000000 1.000000 1.000000 1.000000"; + explodeOnWaterImpact = "0"; + depthTolerance = "5"; + bubbleEmitTime = "0.5"; + faceViewer = "0"; + scale = "1 1 1"; + dryVelocity = "5"; + wetVelocity = "5"; + fizzleTimeMS = "60000"; + lifetimeMS = "60000"; + explodeOnDeath = "0"; + reflectOnWaterImpactAngle = "0"; + deflectionOnWaterImpact = "0"; + fizzleUnderwaterMS = "-1"; + activateDelayMS = "-1"; + doDynamicClientHits = "0"; + sound = "ELFHitTargetSound"; + explosion = "BlasterExplosion"; +}; + +datablock LinearProjectileData(SlowSingeProjectile) { + className = "LinearProjectileData"; + projectileShapeName = "turret_muzzlepoint.dts"; + emitterDelay = "-1"; + velInheritFactor = "0"; + directDamage = "0"; + hasDamageRadius = "0"; + indirectDamage = "0"; + damageRadius = "0"; + radiusDamageType = "0"; + kickBackStrength = "0"; + baseEmitter = "ElfSparksEmitter"; + hasLight = "0"; + lightRadius = "20"; + lightColor = "1.000000 1.000000 1.000000 1.000000"; + hasLightUnderwaterColor = "0"; + underWaterLightColor = "1.000000 1.000000 1.000000 1.000000"; + explodeOnWaterImpact = "0"; + depthTolerance = "5"; + bubbleEmitTime = "0.5"; + faceViewer = "0"; + scale = "1 1 1"; + dryVelocity = "1"; + wetVelocity = "1"; + fizzleTimeMS = "60000"; + lifetimeMS = "60000"; + explodeOnDeath = "0"; + reflectOnWaterImpactAngle = "0"; + deflectionOnWaterImpact = "0"; + fizzleUnderwaterMS = "-1"; + activateDelayMS = "-1"; + doDynamicClientHits = "0"; + sound = "ELFHitTargetSound"; + explosion = "BlasterExplosion"; +}; + + +function singe(%pos,%dir,%size,%type) { + %p = new LinearProjectile() { + dataBlock = %type @"SingeProjectile"; + initialDirection = %dir; + initialPosition = %pos; + }; + +if (%type $= "fast") + %p.schedule((%size/5)*1000,"delete"); +else + %p.schedule((%size)*1000,"delete"); +} + +function edgesinge(%obj) +{ +%objsize = VectorSub(getWords(%obj.getObjectBox(),3,5),getWords(%obj.getObjectBox(),0,2)); +%realsize = realSize(%obj);//VectorMultiply(VectorMultiply(%objsize,%obj.getScale()),"1 1 0"); + +%offset = VectorScale(Realvec(%obj,%realsize),0.49); +%offset2 = VectorScale(VectorCross(VectorNormalize(%offset),realvec(%obj,"0 0 1")),VectorLen(%offset)); +%pos1 = VectorAdd(%obj.getWorldBoxCenter(),%offset); +%pos2 = VectorAdd(%obj.getWorldBoxCenter(),VectorScale(%offset,-1)); +singe(%pos1,Realvec(%obj,"-1 0 0"),GetWord(%realsize,0),"fast"); +singe(%pos1,Realvec(%obj,"0 -1 0"),GetWord(%realsize,1),"fast"); +singe(%pos2,Realvec(%obj,"1 0 0"),GetWord(%realsize,0),"fast"); +singe(%pos2,Realvec(%obj,"0 1 0"),GetWord(%realsize,1),"fast"); +} + +function linksinge(%obj,%pt,%nrm) +{ +if (%nrm !$= "") +{ +%nrm = VectorNormalize(%nrm); +%dir = VectorNormalize(VectorCross(%nrm,Realvec(%obj,"0 0 1"))); +%objsize = VectorSub(getWords(%obj.getObjectBox(),3,5),getWords(%obj.getObjectBox(),0,2)); +%realsize = VectorScale(VectorMultiply(%objsize,%obj.getScale()),0.49); +%side = VirVec(%obj,%nrm); +%oside = VectorCross("0 0 1",%side); + +%forward = Realvec(%obj,VectorMultiply(%realsize,%side)); +%left = Realvec(%obj,VectorMultiply(%realsize,%oside)); +%len = Vectorlen(%left); +%pos1 = VectorAdd(%obj.getWorldBoxCenter(),VectorAdd(%forward,%left)); +%pos2 = VectorAdd(%obj.getWorldBoxCenter(),VectorAdd(%forward,VectorScale(%left,-1))); +singe(%pos1,%dir,%len,"fast"); +singe(%pos2,VectorScale(%dir,-1),%len,"fast"); +} +} + +function floordrill(%obj) +{ +%objsize = VectorSub(getWords(%obj.getObjectBox(),3,5),getWords(%obj.getObjectBox(),0,2)); +%realsize = VectorMultiply(VectorMultiply(%objsize,%obj.getScale()),"0.5 0.5 0.5"); +%forward = VectorScale(realvec(%obj,"1 0 0"),GetWord(%realsize,0)); +%left = VectorScale(realvec(%obj,"0 1 0"),GetWord(%realsize,1)); +%up = VectorScale(realvec(%obj,"0 0 1"),GetWord(%realsize,2)); +%p1 = VectorAdd(VectorAdd(%forward,%left),%up); +%p2 = VectorAdd(VectorAdd(VectorScale(%forward,-1),%left),%up); +%p3 = VectorAdd(VectorAdd(%forward,VectorScale(%left,-1)),%up); +%p4 = VectorAdd(VectorAdd(VectorScale(%forward,-1),VectorScale(%left,-1)),%up); +schedule(0,%obj,"llink",VectorAdd(%p1,%obj.getWorldBoxCenter())); +schedule(500,%obj,"llink",VectorAdd(%p2,%obj.getWorldBoxCenter())); +schedule(1000,%obj,"llink",VectorAdd(%p4,%obj.getWorldBoxCenter())); +schedule(1500,%obj,"llink",VectorAdd(%p3,%obj.getWorldBoxCenter())); +} + +function MSinge(%obj) +{ +%objsize = VectorSub(getWords(%obj.getObjectBox(),3,5),getWords(%obj.getObjectBox(),0,2)); +%realsize = VectorMultiply(VectorMultiply(%objsize,%obj.getScale()),"0.5 0.5 0.5"); +%forward = VectorScale(realvec(%obj,"1 0 0"),GetWord(%realsize,0)); +%left = VectorScale(realvec(%obj,"0 1 0"),GetWord(%realsize,1)); +%up = VectorScale(realvec(%obj,"0 0 -1"),GetWord(%realsize,2)); +%p1 = VectorAdd(VectorAdd(%forward,%left),%up); +%p2 = VectorAdd(VectorAdd(VectorScale(%forward,-1),%left),%up); +%p3 = VectorAdd(VectorAdd(%forward,VectorScale(%left,-1)),%up); +%p4 = VectorAdd(VectorAdd(VectorScale(%forward,-1),VectorScale(%left,-1)),%up); +schedule(0,%obj,"mlink",VectorAdd(%p1,%obj.getWorldBoxCenter())); +schedule(250,%obj,"mlink",VectorAdd(%p2,%obj.getWorldBoxCenter())); +schedule(500,%obj,"mlink",VectorAdd(%p4,%obj.getWorldBoxCenter())); +schedule(750,%obj,"mlink",VectorAdd(%p3,%obj.getWorldBoxCenter())); +} + +function MSinge2(%obj) +{ +%objsize = VectorSub(getWords(%obj.getObjectBox(),3,5),getWords(%obj.getObjectBox(),0,2)); +%realsize = VectorMultiply(VectorMultiply(%objsize,%obj.getScale()),"0.5 0.5 0.5"); +%forward = VectorScale(realvec(%obj,"1 0 0"),GetWord(%realsize,0)); +%left = VectorScale(realvec(%obj,"0 1 0"),GetWord(%realsize,1)); +%up = VectorScale(realvec(%obj,"0 0 1"),GetWord(%realsize,2)); +%p1 = VectorAdd(VectorAdd(%forward,%left),%up); +%p2 = VectorAdd(VectorAdd(VectorScale(%forward,-1),%left),%up); +%p3 = VectorAdd(VectorAdd(%forward,VectorScale(%left,-1)),%up); +%p4 = VectorAdd(VectorAdd(VectorScale(%forward,-1),VectorScale(%left,-1)),%up); +schedule(0,%obj,"mlink",VectorAdd(%p1,%obj.getWorldBoxCenter())); +schedule(250,%obj,"mlink",VectorAdd(%p2,%obj.getWorldBoxCenter())); +schedule(500,%obj,"mlink",VectorAdd(%p4,%obj.getWorldBoxCenter())); +schedule(750,%obj,"mlink",VectorAdd(%p3,%obj.getWorldBoxCenter())); +} + + +function floorlink(%obj,%pt,%nrm) { +%fstat = aboveground(%obj.getworldboxcenter(),1,%obj); +%stat = GetWord(%fstat,0); +//warn(%stat); +if(%stat $= "open" || %stat $= "roof" || %stat $= "shadow") + linksinge(%obj,%pt,%nrm); +else + floordrill(%obj); +} + +function slink(%pt) +{ +createLifeEmitter(%pt, ELFSparksEmitter, 200); +Serverplay3D(SingeLinkSound,%pt); +} + +function mlink(%pt) +{ +createLifeEmitter(%pt, ELFSparksEmitter, 200); +Serverplay3D(SingeLinkSound,%pt); +} + +function llink(%pt) +{ +createLifeEmitter(%pt, SmallLightDamageSmoke, 500); +Serverplay3D(LargeLinkeSound,%pt); +} + +function deployEffect(%obj,%pt,%nrm,%type) +{ +if ($Host::NoDeployEffects) + return ""; +if (%type $= "pad") + { + edgesinge(%obj); + } +else if (%type $= "walk") + { + linksinge(%obj,%pt,%nrm); + } +else if (%type $= "spine") + { + slink(%pt); + } +else if (%type $= "spine1") + { + slink(%pt); + %p2 = VectorAdd( pos( %obj ),realvec( %obj,VectorMultiply("0 0 0.5",%obj.getScale()) ) ); + schedule(500,%obj,"slink",%p2); + } +else if (%type $= "mspine") + { + msinge(%obj); + } +else if (%type $= "mspine1") + { + msinge(%obj); + schedule(1000,%obj,"msinge2",%obj); + } +else if (%type $= "floor") + { + floorlink(%obj,%pt,%nrm); + } +} diff --git a/scripts/damageTypes.cs b/scripts/damageTypes.cs new file mode 100644 index 0000000..5e3edd9 --- /dev/null +++ b/scripts/damageTypes.cs @@ -0,0 +1,754 @@ +//-------------------------------------------------------------------------- +// TYPES OF ALLOWED DAMAGE +//-------------------------------------------------------------------------- + +$DamageType::Default = 0; +$DamageType::Blaster = 1; +$DamageType::Plasma = 2; +$DamageType::Bullet = 3; +$DamageType::Disc = 4; +$DamageType::Grenade = 5; +$DamageType::Laser = 6; // NOTE: This value is referenced directly in code. DO NOT CHANGE! +$DamageType::ELF = 7; +$DamageType::Mortar = 8; +$DamageType::Missile = 9; +$DamageType::ShockLance = 10; +$DamageType::Mine = 11; +$DamageType::Explosion = 12; +$DamageType::Impact = 13; // Object to object collisions +$DamageType::Ground = 14; // Object to ground collisions +$DamageType::Turret = 15; + +$DamageType::PlasmaTurret = 16; +$DamageType::AATurret = 17; +$DamageType::ElfTurret = 18; +$DamageType::MortarTurret = 19; +$DamageType::MissileTurret = 20; +$DamageType::IndoorDepTurret = 21; +$DamageType::OutdoorDepTurret = 22; +$DamageType::SentryTurret = 23; + +$DamageType::OutOfBounds = 24; +$DamageType::Lava = 25; + +$DamageType::ShrikeBlaster = 26; +$DamageType::BellyTurret = 27; +$DamageType::BomberBombs = 28; +$DamageType::TankChaingun = 29; +$DamageType::TankMortar = 30; +$DamageType::SatchelCharge = 31; +$DamageType::MPBMissile = 32; +$DamageType::Lightning = 33; +$DamageType::VehicleSpawn = 34; +$DamageType::ForceFieldPowerup = 35; +$DamageType::Crash = 36; +$DamageType::Debris = 37; + +$DamageType::Meteor = 50; +$DamageType::Cursing = 51; +$DamageType::Idiocy = 52; +$DamageType::SuperChaingun = 53; +$DamageType::KillerFog = 54; + +// DMM -- added so MPBs that blow up under water get a message +$DamageType::Water = 97; + +//Tinman - used in Hunters for cheap bastards ;) +$DamageType::NexusCamping = 98; + +// MES -- added so CTRL-K can get a distinctive message +$DamageType::Suicide = 99; + +// Etc, etc. + +$DamageTypeText[0] = 'default'; +$DamageTypeText[1] = 'blaster'; +$DamageTypeText[2] = 'plasma'; +$DamageTypeText[3] = 'chaingun'; +$DamageTypeText[4] = 'disc'; +$DamageTypeText[5] = 'grenade'; +$DamageTypeText[6] = 'laser'; +$DamageTypeText[7] = 'ELF'; +$DamageTypeText[8] = 'mortar'; +$DamageTypeText[9] = 'missile'; +$DamageTypeText[10] = 'shocklance'; +$DamageTypeText[11] = 'mine'; +$DamageTypeText[12] = 'explosion'; +$DamageTypeText[13] = 'impact'; +$DamageTypeText[14] = 'ground'; +$DamageTypeText[15] = 'turret'; +$DamageTypeText[16] = 'plasma turret'; +$DamageTypeText[17] = 'AA turret'; +$DamageTypeText[18] = 'ELF turret'; +$DamageTypeText[19] = 'mortar turret'; +$DamageTypeText[20] = 'missile turret'; +$DamageTypeText[21] = 'clamp turret'; +$DamageTypeText[22] = 'spike turret'; +$DamageTypeText[23] = 'sentry turret'; +$DamageTypeText[24] = 'out of bounds'; +$DamageTypeText[25] = 'lava'; +$DamageTypeText[26] = 'shrike blaster'; +$DamageTypeText[27] = 'belly turret'; +$DamageTypeText[28] = 'bomber bomb'; +$DamageTypeText[29] = 'tank chaingun'; +$DamageTypeText[30] = 'tank mortar'; +$DamageTypeText[31] = 'satchel charge'; +$DamageTypeText[32] = 'MPB missile'; +$DamageTypeText[33] = 'lighting'; +$DamageTypeText[35] = 'ForceField'; +$DamageTypeText[36] = 'Crash'; + +$DamageTypeText[50] = 'Meteor'; +$DamageTypeText[51] = 'Cursing'; +$DamageTypeText[52] = 'Idiocy'; +$DamageTypeText[53] = 'SuperChaingun'; +$DamageTypeText[54] = 'KillerFog'; + +$DamageTypeText[98] = 'nexus camping'; +$DamageTypeText[99] = 'suicide'; + + +// ##### PLEASE DO NOT REORDER THE DAMAGE PROFILE TABLES BELOW ##### +// (They are set up in the same order as the "Weapons Matrix.xls" sheet for ease of reference when balancing) + +//---------------------------------------------------------------------------- +// VEHICLE DAMAGE PROFILES +//---------------------------------------------------------------------------- + +//**** SHRIKE SCOUT FIGHTER **** +datablock SimDataBlock(ShrikeDamageProfile) +{ + shieldDamageScale[$DamageType::Blaster] = 1.75; + shieldDamageScale[$DamageType::Bullet] = 1.75; + shieldDamageScale[$DamageType::ELF] = 1.0; + shieldDamageScale[$DamageType::ElfTurret] = 1.0; + shieldDamageScale[$DamageType::ShockLance] = 0.5; + + shieldDamageScale[$DamageType::Laser] = 1.0; + shieldDamageScale[$DamageType::ShrikeBlaster] = 4.0; + shieldDamageScale[$DamageType::BellyTurret] = 2.0; + shieldDamageScale[$DamageType::AATurret] = 3.0; + shieldDamageScale[$DamageType::IndoorDepTurret] = 2.5; + shieldDamageScale[$DamageType::OutdoorDepTurret] = 2.5; + shieldDamageScale[$DamageType::SentryTurret] = 2.5; + shieldDamageScale[$DamageType::Disc] = 1.5; + shieldDamageScale[$DamageType::Grenade] = 1.0; + shieldDamageScale[$DamageType::Mine] = 3.0; + shieldDamageScale[$DamageType::Missile] = 3.0; + shieldDamageScale[$DamageType::Mortar] = 2.0; + shieldDamageScale[$DamageType::Plasma] = 1.0; + shieldDamageScale[$DamageType::BomberBombs] = 3.0; + shieldDamageScale[$DamageType::TankChaingun] = 3.0; + shieldDamageScale[$DamageType::TankMortar] = 2.0; + shieldDamageScale[$DamageType::MissileTurret] = 3.0; + shieldDamageScale[$DamageType::MortarTurret] = 2.0; + shieldDamageScale[$DamageType::PlasmaTurret] = 2.0; + shieldDamageScale[$DamageType::SatchelCharge] = 3.5; + shieldDamageScale[$DamageType::Default] = 1.0; + shieldDamageScale[$DamageType::Impact] = 1.1; + shieldDamageScale[$DamageType::Ground] = 1.0; + shieldDamageScale[$DamageType::Explosion] = 3.0; + shieldDamageScale[$DamageType::Lightning] = 10.0; + shieldDamageScale[$DamageType::Debris] = 1.0; + + damageScale[$DamageType::Blaster] = 1.0; + damageScale[$DamageType::Bullet] = 1.0; + damageScale[$DamageType::ELF] = 0.0; + damageScale[$DamageType::ElfTurret] = 1.0; + damageScale[$DamageType::ShockLance] = 0.50; + damageScale[$DamageType::Laser] = 1.0; + damageScale[$DamageType::ShrikeBlaster] = 3.5; + damageScale[$DamageType::BellyTurret] = 1.2; + damageScale[$DamageType::AATurret] = 1.5; + damageScale[$DamageType::IndoorDepTurret] = 1.5; + damageScale[$DamageType::OutdoorDepTurret] = 1.5; + damageScale[$DamageType::SentryTurret] = 1.5; + damageScale[$DamageType::Disc] = 1.25; + damageScale[$DamageType::Grenade] = 0.75; + damageScale[$DamageType::Mine] = 4.0; + damageScale[$DamageType::Missile] = 2.0; + damageScale[$DamageType::Mortar] = 2.0; + damageScale[$DamageType::Plasma] = 0.5; + damageScale[$DamageType::BomberBombs] = 2.0; + damageScale[$DamageType::TankChaingun] = 2.0; + damageScale[$DamageType::TankMortar] = 2.0; + damageScale[$DamageType::MissileTurret] = 1.5; + damageScale[$DamageType::MortarTurret] = 2.0; + damageScale[$DamageType::PlasmaTurret] = 2.0; + damageScale[$DamageType::SatchelCharge] = 3.5; + damageScale[$DamageType::Default] = 1.0; + damageScale[$DamageType::Impact] = 1.1; + damageScale[$DamageType::Ground] = 1.0; + damageScale[$DamageType::Explosion] = 2.0; + damageScale[$DamageType::Lightning] = 10.0; + damageScale[$DamageType::Debris] = 0.75; +}; + +//**** THUNDERSWORD BOMBER **** +datablock SimDataBlock(BomberDamageProfile) +{ + shieldDamageScale[$DamageType::Blaster] = 1.0; + shieldDamageScale[$DamageType::Bullet] = 1.0; + shieldDamageScale[$DamageType::ELF] = 1.0; + shieldDamageScale[$DamageType::ELFturret] = 1.0; + shieldDamageScale[$DamageType::ShockLance] = 0.5; + shieldDamageScale[$DamageType::Laser] = 1.0; + shieldDamageScale[$DamageType::ShrikeBlaster] = 3.5; + shieldDamageScale[$DamageType::BellyTurret] = 2.0; + shieldDamageScale[$DamageType::AATurret] = 3.0; + shieldDamageScale[$DamageType::IndoorDepTurret] = 2.25; + shieldDamageScale[$DamageType::OutdoorDepTurret] = 2.25; + shieldDamageScale[$DamageType::SentryTurret] = 2.25; + shieldDamageScale[$DamageType::Disc] = 1.0; + shieldDamageScale[$DamageType::Grenade] = 1.0; + shieldDamageScale[$DamageType::Mine] = 3.0; + shieldDamageScale[$DamageType::Missile] = 3.0; + shieldDamageScale[$DamageType::Mortar] = 2.0; + shieldDamageScale[$DamageType::Plasma] = 1.0; + shieldDamageScale[$DamageType::BomberBombs] = 3.0; + shieldDamageScale[$DamageType::TankChaingun] = 3.0; + shieldDamageScale[$DamageType::TankMortar] = 2.0; + shieldDamageScale[$DamageType::MissileTurret] = 3.0; + shieldDamageScale[$DamageType::MortarTurret] = 2.0; + shieldDamageScale[$DamageType::PlasmaTurret] = 2.0; + shieldDamageScale[$DamageType::SatchelCharge] = 3.5; + shieldDamageScale[$DamageType::Default] = 1.0; + shieldDamageScale[$DamageType::Impact] = 0.8; + shieldDamageScale[$DamageType::Ground] = 1.0; + shieldDamageScale[$DamageType::Explosion] = 3.0; + shieldDamageScale[$DamageType::Lightning] = 10.0; + + damageScale[$DamageType::Blaster] = 0.75; + damageScale[$DamageType::Bullet] = 0.75; + damageScale[$DamageType::ELF] = 0.0; + damageScale[$DamageType::ELFturret] = 1.0; + damageScale[$DamageType::ShockLance] = 0.50; + damageScale[$DamageType::Laser] = 1.0; + damageScale[$DamageType::ShrikeBlaster] = 2.5; + damageScale[$DamageType::BellyTurret] = 1.2; + damageScale[$DamageType::AATurret] = 1.5; + damageScale[$DamageType::IndoorDepTurret] = 1.25; + damageScale[$DamageType::OutdoorDepTurret] = 1.25; + damageScale[$DamageType::SentryTurret] = 1.25; + damageScale[$DamageType::Disc] = 1.0; + damageScale[$DamageType::Grenade] = 0.75; + damageScale[$DamageType::Mine] = 4.0; + damageScale[$DamageType::Missile] = 1.5; + damageScale[$DamageType::Mortar] = 2.0; + damageScale[$DamageType::Plasma] = 0.5; + damageScale[$DamageType::BomberBombs] = 2.0; + damageScale[$DamageType::TankChaingun] = 2.0; + damageScale[$DamageType::TankMortar] = 2.0; + damageScale[$DamageType::MissileTurret] = 1.5; + damageScale[$DamageType::MortarTurret] = 2.0; + damageScale[$DamageType::PlasmaTurret] = 2.0; + damageScale[$DamageType::SatchelCharge] = 3.5; + damageScale[$DamageType::Default] = 1.0; + damageScale[$DamageType::Impact] = 0.8; + damageScale[$DamageType::Ground] = 1.0; + damageScale[$DamageType::Explosion] = 2.0; + damageScale[$DamageType::Lightning] = 10.0; +}; + +//**** HAVOC TRANSPORT **** +datablock SimDataBlock(HavocDamageProfile) +{ + shieldDamageScale[$DamageType::Blaster] = 1.0; + shieldDamageScale[$DamageType::Bullet] = 1.0; + shieldDamageScale[$DamageType::ELF] = 1.0; + shieldDamageScale[$DamageType::ELFturret] = 1.0; + shieldDamageScale[$DamageType::ShockLance] = 0.5; + shieldDamageScale[$DamageType::Laser] = 1.0; + shieldDamageScale[$DamageType::ShrikeBlaster] = 3.5; + shieldDamageScale[$DamageType::BellyTurret] = 2.0; + shieldDamageScale[$DamageType::AATurret] = 3.0; + shieldDamageScale[$DamageType::IndoorDepTurret] = 2.25; + shieldDamageScale[$DamageType::OutdoorDepTurret] = 2.25; + shieldDamageScale[$DamageType::SentryTurret] = 2.25; + shieldDamageScale[$DamageType::Disc] = 1.0; + shieldDamageScale[$DamageType::Grenade] = 1.0; + shieldDamageScale[$DamageType::Mine] = 3.0; + shieldDamageScale[$DamageType::Missile] = 3.0; + shieldDamageScale[$DamageType::Mortar] = 2.0; + shieldDamageScale[$DamageType::Plasma] = 1.0; + shieldDamageScale[$DamageType::BomberBombs] = 3.0; + shieldDamageScale[$DamageType::TankChaingun] = 3.0; + shieldDamageScale[$DamageType::TankMortar] = 2.0; + shieldDamageScale[$DamageType::MissileTurret] = 3.0; + shieldDamageScale[$DamageType::MortarTurret] = 2.0; + shieldDamageScale[$DamageType::PlasmaTurret] = 2.0; + shieldDamageScale[$DamageType::SatchelCharge] = 3.5; + shieldDamageScale[$DamageType::Default] = 1.0; + shieldDamageScale[$DamageType::Impact] = 0.5; + shieldDamageScale[$DamageType::Ground] = 1.0; + shieldDamageScale[$DamageType::Explosion] = 3.0; + shieldDamageScale[$DamageType::Lightning] = 10.0; + + damageScale[$DamageType::Blaster] = 0.75; + damageScale[$DamageType::Bullet] = 0.75; + damageScale[$DamageType::ELF] = 0.0; + damageScale[$DamageType::ELFturret] = 1.0; + damageScale[$DamageType::ShockLance] = 0.50; + damageScale[$DamageType::Laser] = 1.0; + damageScale[$DamageType::ShrikeBlaster] = 2.5; + damageScale[$DamageType::BellyTurret] = 1.2; + damageScale[$DamageType::AATurret] = 1.5; + damageScale[$DamageType::IndoorDepTurret] = 1.25; + damageScale[$DamageType::OutdoorDepTurret] = 1.25; + damageScale[$DamageType::SentryTurret] = 1.25; + damageScale[$DamageType::Disc] = 1.0; + damageScale[$DamageType::Grenade] = 0.75; + damageScale[$DamageType::Mine] = 4.0; + damageScale[$DamageType::Missile] = 1.5; + damageScale[$DamageType::Mortar] = 2.0; + damageScale[$DamageType::Plasma] = 0.5; + damageScale[$DamageType::BomberBombs] = 2.0; + damageScale[$DamageType::TankChaingun] = 2.0; + damageScale[$DamageType::TankMortar] = 2.0; + damageScale[$DamageType::MissileTurret] = 1.5; + damageScale[$DamageType::MortarTurret] = 2.0; + damageScale[$DamageType::PlasmaTurret] = 2.0; + damageScale[$DamageType::SatchelCharge] = 3.5; + damageScale[$DamageType::Default] = 1.0; + damageScale[$DamageType::Impact] = 0.5; + damageScale[$DamageType::Ground] = 1.0; + damageScale[$DamageType::Explosion] = 2.0; + damageScale[$DamageType::Lightning] = 10.0; +}; + +//**** WILDCAT GRAV CYCLE **** +datablock SimDataBlock(WildcatDamageProfile) +{ + shieldDamageScale[$DamageType::Blaster] = 2.0; + shieldDamageScale[$DamageType::Bullet] = 2.5; + shieldDamageScale[$DamageType::ELF] = 1.0; + shieldDamageScale[$DamageType::ELFturret] = 1.0; + shieldDamageScale[$DamageType::ShockLance] = 1.0; + shieldDamageScale[$DamageType::Laser] = 4.0; + shieldDamageScale[$DamageType::ShrikeBlaster] = 6.0; + shieldDamageScale[$DamageType::BellyTurret] = 2.0; + shieldDamageScale[$DamageType::AATurret] = 2.0; + shieldDamageScale[$DamageType::IndoorDepTurret] = 2.5; + shieldDamageScale[$DamageType::OutdoorDepTurret] = 2.5; + shieldDamageScale[$DamageType::Disc] = 2.5; + shieldDamageScale[$DamageType::Grenade] = 2.0; + shieldDamageScale[$DamageType::Mine] = 4.0; + shieldDamageScale[$DamageType::Missile] = 4.0; + shieldDamageScale[$DamageType::Mortar] = 2.0; + shieldDamageScale[$DamageType::Plasma] = 2.0; + shieldDamageScale[$DamageType::BomberBombs] = 2.5; + shieldDamageScale[$DamageType::TankChaingun] = 3.0; + shieldDamageScale[$DamageType::TankMortar] = 2.0; + shieldDamageScale[$DamageType::MissileTurret] = 4.0; + shieldDamageScale[$DamageType::MortarTurret] = 2.0; + shieldDamageScale[$DamageType::PlasmaTurret] = 2.0; + shieldDamageScale[$DamageType::SatchelCharge] = 3.0; + shieldDamageScale[$DamageType::Default] = 1.0; + shieldDamageScale[$DamageType::Impact] = 1.25; + shieldDamageScale[$DamageType::Ground] = 1.0; + shieldDamageScale[$DamageType::Explosion] = 2.0; + shieldDamageScale[$DamageType::Lightning] = 5.0; + + damageScale[$DamageType::Blaster] = 1.5; + damageScale[$DamageType::Bullet] = 1.2; + damageScale[$DamageType::ELF] = 0.0; + damageScale[$DamageType::ELFturret] = 1.0; + damageScale[$DamageType::ShockLance] = 0.50; + damageScale[$DamageType::Laser] = 2.0; + damageScale[$DamageType::ShrikeBlaster] = 4.0; + damageScale[$DamageType::BellyTurret] = 1.5; + damageScale[$DamageType::AATurret] = 1.0; + damageScale[$DamageType::IndoorDepTurret] = 1.0; + damageScale[$DamageType::OutdoorDepTurret] = 1.0; + damageScale[$DamageType::Disc] = 1.25; + damageScale[$DamageType::Grenade] = 1.0; + damageScale[$DamageType::Mine] = 4.0; + damageScale[$DamageType::Missile] = 1.2; + damageScale[$DamageType::Mortar] = 1.0; + damageScale[$DamageType::Plasma] = 1.5; + damageScale[$DamageType::BomberBombs] = 2.0; + damageScale[$DamageType::TankChaingun] = 2.0; + damageScale[$DamageType::TankMortar] = 1.0; + damageScale[$DamageType::MissileTurret] = 1.2; + damageScale[$DamageType::MortarTurret] = 1.0; + damageScale[$DamageType::PlasmaTurret] = 1.0; + damageScale[$DamageType::SatchelCharge] = 2.2; + damageScale[$DamageType::Default] = 1.0; + damageScale[$DamageType::Impact] = 1.25; + damageScale[$DamageType::Ground] = 1.0; + damageScale[$DamageType::Explosion] = 1.0; + damageScale[$DamageType::Lightning] = 5.0; +}; + +//**** BEOWULF TANK **** +datablock SimDataBlock(TankDamageProfile) +{ + shieldDamageScale[$DamageType::Blaster] = 0.6; + shieldDamageScale[$DamageType::Bullet] = 0.75; + shieldDamageScale[$DamageType::ELF] = 1.0; + shieldDamageScale[$DamageType::ELFturret] = 1.0; + shieldDamageScale[$DamageType::ShockLance] = 0.5; + shieldDamageScale[$DamageType::Laser] = 1.0; + shieldDamageScale[$DamageType::ShrikeBlaster] = 1.75; + shieldDamageScale[$DamageType::BellyTurret] = 1.25; + shieldDamageScale[$DamageType::AATurret] = 0.8; + shieldDamageScale[$DamageType::IndoorDepTurret] = 1.0; + shieldDamageScale[$DamageType::OutdoorDepTurret] = 1.0; + shieldDamageScale[$DamageType::Disc] = 0.8; + shieldDamageScale[$DamageType::Grenade] = 0.8; + shieldDamageScale[$DamageType::Mine] = 3.25; + shieldDamageScale[$DamageType::Missile] = 2.0; + shieldDamageScale[$DamageType::Mortar] = 1.7; + shieldDamageScale[$DamageType::Plasma] = 1.0; + shieldDamageScale[$DamageType::BomberBombs] = 1.5; + shieldDamageScale[$DamageType::TankChaingun] = 1.5; + shieldDamageScale[$DamageType::TankMortar] = 1.8; + shieldDamageScale[$DamageType::MissileTurret] = 1.25; + shieldDamageScale[$DamageType::MortarTurret] = 1.0; + shieldDamageScale[$DamageType::PlasmaTurret] = 1.25; + shieldDamageScale[$DamageType::SatchelCharge] = 2.0; + shieldDamageScale[$DamageType::Default] = 1.0; + shieldDamageScale[$DamageType::Impact] = 0.75; + shieldDamageScale[$DamageType::Ground] = 0.75; + shieldDamageScale[$DamageType::Explosion] = 2.0; + shieldDamageScale[$DamageType::Lightning] = 10.0; + + damageScale[$DamageType::Blaster] = 0.75; + damageScale[$DamageType::Bullet] = 0.75; + damageScale[$DamageType::ELF] = 0.0; + damageScale[$DamageType::ELFturret] =1.0; + damageScale[$DamageType::ShockLance] = 0.50; + damageScale[$DamageType::Laser] = 1.0; + damageScale[$DamageType::ShrikeBlaster] = 2.0; + damageScale[$DamageType::BellyTurret] = 1.0; + damageScale[$DamageType::AATurret] = 1.0; + damageScale[$DamageType::IndoorDepTurret] = 1.0; + damageScale[$DamageType::OutdoorDepTurret] = 1.0; + damageScale[$DamageType::Disc] = 1.0; + damageScale[$DamageType::Grenade] = 1.0; + damageScale[$DamageType::Mine] = 2.25; + damageScale[$DamageType::Missile] = 1.25; + damageScale[$DamageType::Mortar] = 1.4; + damageScale[$DamageType::Plasma] = 0.5; + damageScale[$DamageType::BomberBombs] = 1.0; + damageScale[$DamageType::TankChaingun] = 0.75; + damageScale[$DamageType::TankMortar] = 1.6; + damageScale[$DamageType::MissileTurret] = 1.25; + damageScale[$DamageType::MortarTurret] = 1.0; + damageScale[$DamageType::PlasmaTurret] = 1.0; + damageScale[$DamageType::SatchelCharge] = 2.0; + damageScale[$DamageType::Default] = 1.0; + damageScale[$DamageType::Impact] = 0.75; + damageScale[$DamageType::Ground] = 0.75; + damageScale[$DamageType::Explosion] = 1.0; + damageScale[$DamageType::Lightning] = 10.0; +}; + +//**** JERICHO MPB **** +datablock SimDataBlock(MPBDamageProfile) +{ + shieldDamageScale[$DamageType::Blaster] = 0.6; + shieldDamageScale[$DamageType::Bullet] = 0.75; + shieldDamageScale[$DamageType::ELF] = 1.0; + shieldDamageScale[$DamageType::ELFturret] = 1.0; + shieldDamageScale[$DamageType::ShockLance] = 0.5; + shieldDamageScale[$DamageType::Laser] = 1.0; + shieldDamageScale[$DamageType::ShrikeBlaster] = 1.75; + shieldDamageScale[$DamageType::BellyTurret] = 1.25; + shieldDamageScale[$DamageType::AATurret] = 0.8; + shieldDamageScale[$DamageType::IndoorDepTurret] = 1.0; + shieldDamageScale[$DamageType::OutdoorDepTurret] = 1.0; + shieldDamageScale[$DamageType::Disc] = 0.8; + shieldDamageScale[$DamageType::Grenade] = 0.8; + shieldDamageScale[$DamageType::Mine] = 3.25; + shieldDamageScale[$DamageType::Missile] = 2.0; + shieldDamageScale[$DamageType::Mortar] = 0.8; + shieldDamageScale[$DamageType::Plasma] = 1.0; + shieldDamageScale[$DamageType::BomberBombs] = 1.5; + shieldDamageScale[$DamageType::TankChaingun] = 1.5; + shieldDamageScale[$DamageType::TankMortar] = 1.4; + shieldDamageScale[$DamageType::MissileTurret] = 1.25; + shieldDamageScale[$DamageType::MortarTurret] = 1.0; + shieldDamageScale[$DamageType::PlasmaTurret] = 1.25; + shieldDamageScale[$DamageType::SatchelCharge] = 2.0; + shieldDamageScale[$DamageType::Default] = 1.0; + shieldDamageScale[$DamageType::Impact] = 0.5; + shieldDamageScale[$DamageType::Ground] = 0.5; + shieldDamageScale[$DamageType::Explosion] = 2.0; + shieldDamageScale[$DamageType::Lightning] = 10.0; + + damageScale[$DamageType::Blaster] = 0.75; + damageScale[$DamageType::Bullet] = 0.75; + damageScale[$DamageType::ELF] = 0.0; + damageScale[$DamageType::ELFturret] = 0.0; + damageScale[$DamageType::ShockLance] = 0.50; + damageScale[$DamageType::Laser] = 1.0; + damageScale[$DamageType::ShrikeBlaster] = 2.0; + damageScale[$DamageType::BellyTurret] = 1.0; + damageScale[$DamageType::AATurret] = 1.0; + damageScale[$DamageType::IndoorDepTurret] = 1.0; + damageScale[$DamageType::OutdoorDepTurret] = 1.0; + damageScale[$DamageType::Disc] = 1.0; + damageScale[$DamageType::Grenade] = 1.0; + damageScale[$DamageType::Mine] = 2.25; + damageScale[$DamageType::Missile] = 1.25; + damageScale[$DamageType::Mortar] = 1.0; + damageScale[$DamageType::Plasma] = 0.5; + damageScale[$DamageType::BomberBombs] = 1.0; + damageScale[$DamageType::TankChaingun] = 0.75; + damageScale[$DamageType::TankMortar] = 1.0; + damageScale[$DamageType::MissileTurret] = 1.25; + damageScale[$DamageType::MortarTurret] = 1.0; + damageScale[$DamageType::PlasmaTurret] = 1.0; + damageScale[$DamageType::SatchelCharge] = 2.0; + damageScale[$DamageType::Default] = 1.0; + damageScale[$DamageType::Impact] = 0.5; + damageScale[$DamageType::Ground] = 0.5; + damageScale[$DamageType::Explosion] = 1.0; + damageScale[$DamageType::Lightning] = 10.0; +}; + +//---------------------------------------------------------------------------- +// TURRET DAMAGE PROFILES +//---------------------------------------------------------------------------- + +datablock SimDataBlock(TurretDamageProfile) +{ + shieldDamageScale[$DamageType::Blaster] = 0.8; + shieldDamageScale[$DamageType::Bullet] = 0.8; + shieldDamageScale[$DamageType::ELF] = 1.0; + shieldDamageScale[$DamageType::ELFturret] = 1.0; + shieldDamageScale[$DamageType::ShockLance] = 0.5; + shieldDamageScale[$DamageType::Laser] = 1.0; + shieldDamageScale[$DamageType::ShrikeBlaster] = 3.0; + shieldDamageScale[$DamageType::BellyTurret] = 2.0; + shieldDamageScale[$DamageType::AATurret] = 1.0; + shieldDamageScale[$DamageType::IndoorDepTurret] = 1.0; + shieldDamageScale[$DamageType::OutdoorDepTurret] = 1.0; + shieldDamageScale[$DamageType::SentryTurret] = 1.0; + shieldDamageScale[$DamageType::Disc] = 1.0; + shieldDamageScale[$DamageType::Grenade] = 1.5; + shieldDamageScale[$DamageType::Mine] = 3.0; + shieldDamageScale[$DamageType::Missile] = 3.0; + shieldDamageScale[$DamageType::Mortar] = 3.0; + shieldDamageScale[$DamageType::Plasma] = 1.0; + shieldDamageScale[$DamageType::BomberBombs] = 2.0; + shieldDamageScale[$DamageType::TankChaingun] = 1.5; + shieldDamageScale[$DamageType::TankMortar] = 3.0; + shieldDamageScale[$DamageType::MissileTurret] = 3.0; + shieldDamageScale[$DamageType::MortarTurret] = 3.0; + shieldDamageScale[$DamageType::PlasmaTurret] = 2.0; + shieldDamageScale[$DamageType::SatchelCharge] = 4.5; + shieldDamageScale[$DamageType::Default] = 1.0; + shieldDamageScale[$DamageType::Impact] = 1.0; + shieldDamageScale[$DamageType::Ground] = 1.0; + shieldDamageScale[$DamageType::Explosion] = 2.0; + shieldDamageScale[$DamageType::Lightning] = 5.0; + + damageScale[$DamageType::Blaster] = 0.8; + damageScale[$DamageType::Bullet] = 0.9; + damageScale[$DamageType::ELF] = 0.0; + damageScale[$DamageType::ELFturret] = 1.0; + damageScale[$DamageType::ShockLance] = 0.50; + damageScale[$DamageType::Laser] = 1.0; + damageScale[$DamageType::ShrikeBlaster] = 1.0; + damageScale[$DamageType::BellyTurret] = 0.6; + damageScale[$DamageType::AATurret] = 1.0; + damageScale[$DamageType::IndoorDepTurret] = 1.0; + damageScale[$DamageType::OutdoorDepTurret] = 1.0; + damageScale[$DamageType::SentryTurret] = 1.0; + damageScale[$DamageType::Disc] = 1.1; + damageScale[$DamageType::Grenade] = 1.0; + damageScale[$DamageType::Mine] = 1.5; + damageScale[$DamageType::Missile] = 1.25; + damageScale[$DamageType::Mortar] = 1.25; + damageScale[$DamageType::Plasma] = 0.75; + damageScale[$DamageType::BomberBombs] = 1.0; + damageScale[$DamageType::TankChaingun] = 1.25; + damageScale[$DamageType::TankMortar] = 1.25; + damageScale[$DamageType::MissileTurret] = 1.25; + damageScale[$DamageType::MortarTurret] = 1.25; + damageScale[$DamageType::PlasmaTurret] = 1.25; + damageScale[$DamageType::SatchelCharge] = 1.5; + damageScale[$DamageType::Default] = 1.0; + damageScale[$DamageType::Impact] = 1.0; + damageScale[$DamageType::Ground] = 1.0; + damageScale[$DamageType::Explosion] = 1.0; + damageScale[$DamageType::Lightning] = 5.0; +}; + +//---------------------------------------------------------------------------- +// STATIC SHAPE DAMAGE PROFILES +//---------------------------------------------------------------------------- + +datablock SimDataBlock(StaticShapeDamageProfile) +{ + shieldDamageScale[$DamageType::Blaster] = 0.8; + shieldDamageScale[$DamageType::Bullet] = 1.0; + shieldDamageScale[$DamageType::ELF] = 1.0; + shieldDamageScale[$DamageType::ELFturret] = 1.0; + shieldDamageScale[$DamageType::ShockLance] = 1.0; + shieldDamageScale[$DamageType::Laser] = 1.0; + shieldDamageScale[$DamageType::ShrikeBlaster] = 2.0; + shieldDamageScale[$DamageType::BellyTurret] = 1.5; + shieldDamageScale[$DamageType::AATurret] = 1.0; + shieldDamageScale[$DamageType::IndoorDepTurret] = 1.0; + shieldDamageScale[$DamageType::OutdoorDepTurret] = 1.0; + shieldDamageScale[$DamageType::Turret] = 1.0; + shieldDamageScale[$DamageType::SentryTurret] = 1.0; + shieldDamageScale[$DamageType::Disc] = 1.0; + shieldDamageScale[$DamageType::Grenade] = 1.2; + shieldDamageScale[$DamageType::Mine] = 2.0; + shieldDamageScale[$DamageType::Missile] = 3.0; + shieldDamageScale[$DamageType::Mortar] = 3.0; + shieldDamageScale[$DamageType::Plasma] = 1.5; + shieldDamageScale[$DamageType::BomberBombs] = 2.0; + shieldDamageScale[$DamageType::TankChaingun] = 1.5; + shieldDamageScale[$DamageType::TankMortar] = 3.0; + shieldDamageScale[$DamageType::MissileTurret] = 3.0; + shieldDamageScale[$DamageType::MortarTurret] = 3.0; + shieldDamageScale[$DamageType::PlasmaTurret] = 2.0; + shieldDamageScale[$DamageType::SatchelCharge] = 6.0; + shieldDamageScale[$DamageType::Default] = 1.0; + shieldDamageScale[$DamageType::Impact] = 1.25; + shieldDamageScale[$DamageType::Ground] = 1.0; + shieldDamageScale[$DamageType::Explosion] = 2.0; + shieldDamageScale[$DamageType::Lightning] = 5.0; + + damageScale[$DamageType::Blaster] = 1.0; + damageScale[$DamageType::Bullet] = 1.0; + damageScale[$DamageType::ELF] = 0.0; + damageScale[$DamageType::ELFturret] = 1.0; + damageScale[$DamageType::ShockLance] = 1.0; + damageScale[$DamageType::Laser] = 1.0; + damageScale[$DamageType::ShrikeBlaster] = 2.0; + damageScale[$DamageType::BellyTurret] = 1.2; + damageScale[$DamageType::AATurret] = 1.0; + damageScale[$DamageType::IndoorDepTurret] = 1.0; + damageScale[$DamageType::OutdoorDepTurret] = 1.0; + damageScale[$DamageType::SentryTurret] = 1.0; + damageScale[$DamageType::Disc] = 1.15; + damageScale[$DamageType::Grenade] = 1.2; + damageScale[$DamageType::Mine] = 2.0; + damageScale[$DamageType::Missile] = 2.0; + damageScale[$DamageType::Mortar] = 2.0; + damageScale[$DamageType::Plasma] = 1.25; + damageScale[$DamageType::BomberBombs] = 1.0; + damageScale[$DamageType::TankChaingun] = 1.0; + damageScale[$DamageType::TankMortar] = 2.0; + damageScale[$DamageType::MissileTurret] = 2.0; + damageScale[$DamageType::MortarTurret] = 2.0; + damageScale[$DamageType::PlasmaTurret] = 2.0; + damageScale[$DamageType::SatchelCharge] = 4.0; + damageScale[$DamageType::Default] = 1.0; + damageScale[$DamageType::Impact] = 1.25; + damageScale[$DamageType::Ground] = 1.0; + damageScale[$DamageType::Explosion] = 1.0; + damageScale[$DamageType::Lightning] = 5.0; +}; + +//---------------------------------------------------------------------------- +// PLAYER DAMAGE PROFILES +//---------------------------------------------------------------------------- + +datablock SimDataBlock(LightPlayerDamageProfile) +{ + damageScale[$DamageType::Blaster] = 1.3; + damageScale[$DamageType::Bullet] = 1.2; + damageScale[$DamageType::ELF] = 0.75; + damageScale[$DamageType::ELFturret] = 0.75; + damageScale[$DamageType::ShockLance] = 1.0; + damageScale[$DamageType::Laser] = 1.12; + damageScale[$DamageType::ShrikeBlaster] = 1.10; + damageScale[$DamageType::BellyTurret] = 1.0; + damageScale[$DamageType::AATurret] = 0.7; + damageScale[$DamageType::IndoorDepTurret] = 1.3; + damageScale[$DamageType::OutdoorDepTurret] = 1.3; + damageScale[$DamageType::SentryTurret] = 1.0; + damageScale[$DamageType::Disc] = 1.0; + damageScale[$DamageType::Grenade] = 1.2; + damageScale[$DamageType::Mine] = 1.0; + damageScale[$DamageType::Missile] = 1.0; + damageScale[$DamageType::Mortar] = 1.3; + damageScale[$DamageType::Plasma] = 1.0; + damageScale[$DamageType::BomberBombs] = 3.0; + damageScale[$DamageType::TankChaingun] = 1.7; + damageScale[$DamageType::TankMortar] = 1.0; + damageScale[$DamageType::MissileTurret] = 1.0; + damageScale[$DamageType::MortarTurret] = 1.3; + damageScale[$DamageType::PlasmaTurret] = 1.0; + damageScale[$DamageType::SatchelCharge] = 3.0; + damageScale[$DamageType::Default] = 1.0; + damageScale[$DamageType::Impact] = 1.2; + damageScale[$DamageType::Ground] = 1.0; + damageScale[$DamageType::Explosion] = 1.0; + damageScale[$DamageType::Lightning] = 1.0; +}; + +datablock SimDataBlock(MediumPlayerDamageProfile) +{ + damageScale[$DamageType::Blaster] = 1.0; + damageScale[$DamageType::Bullet] = 1.0; + damageScale[$DamageType::ELF] = 0.75; + damageScale[$DamageType::ELFturret] = 0.75; + damageScale[$DamageType::ShockLance] = 1.0; + damageScale[$DamageType::Laser] = 1.1; + damageScale[$DamageType::ShrikeBlaster] = 1.0; + damageScale[$DamageType::BellyTurret] = 1.0; + damageScale[$DamageType::AATurret] = 0.7; + damageScale[$DamageType::IndoorDepTurret] = 1.0; + damageScale[$DamageType::OutdoorDepTurret] = 1.0; + damageScale[$DamageType::SentryTurret] = 1.0; + damageScale[$DamageType::Disc] = 0.8; + damageScale[$DamageType::Grenade] = 1.0; + damageScale[$DamageType::Mine] = 0.9; + damageScale[$DamageType::Missile] = 0.8; + damageScale[$DamageType::Mortar] = 1.0; + damageScale[$DamageType::Plasma] = 0.65; + damageScale[$DamageType::BomberBombs] = 3.0; + damageScale[$DamageType::TankChaingun] = 1.5; + damageScale[$DamageType::TankMortar] = 0.85; + damageScale[$DamageType::MissileTurret] = 0.8; + damageScale[$DamageType::MortarTurret] = 1.0; + damageScale[$DamageType::PlasmaTurret] = 0.65; + damageScale[$DamageType::SatchelCharge] = 3.0; + damageScale[$DamageType::Default] = 1.0; + damageScale[$DamageType::Impact] = 1.0; + damageScale[$DamageType::Ground] = 1.0; + damageScale[$DamageType::Explosion] = 0.8; + damageScale[$DamageType::Lightning] = 1.2; +}; + +datablock SimDataBlock(HeavyPlayerDamageProfile) +{ + damageScale[$DamageType::Blaster] = 0.7; + damageScale[$DamageType::Bullet] = 0.6; + damageScale[$DamageType::ELF] = 0.75; + damageScale[$DamageType::ELFturret] = 0.75; + damageScale[$DamageType::ShockLance] = 1.0; + damageScale[$DamageType::Laser] = 0.67; + damageScale[$DamageType::ShrikeBlaster] = 0.8; + damageScale[$DamageType::BellyTurret] = 0.8; + damageScale[$DamageType::AATurret] = 0.6; + damageScale[$DamageType::IndoorDepTurret] = 0.7; + damageScale[$DamageType::OutdoorDepTurret] = 0.7; + damageScale[$DamageType::SentryTurret] = 1.0; + damageScale[$DamageType::Disc] = 0.6; + damageScale[$DamageType::Grenade] = 0.8; + damageScale[$DamageType::Mine] = 0.8; + damageScale[$DamageType::Missile] = 0.6; + damageScale[$DamageType::Mortar] = 0.7; + damageScale[$DamageType::Plasma] = 0.4; + damageScale[$DamageType::BomberBombs] = 3.0; + damageScale[$DamageType::TankChaingun] = 1.3; + damageScale[$DamageType::TankMortar] = 0.7; + damageScale[$DamageType::MissileTurret] = 0.6; + damageScale[$DamageType::MortarTurret] = 0.6; + damageScale[$DamageType::PlasmaTurret] = 0.4; + damageScale[$DamageType::SatchelCharge] = 3.0; + damageScale[$DamageType::Default] = 1.0; + damageScale[$DamageType::Impact] = 0.8; + damageScale[$DamageType::Ground] = 1.0; + damageScale[$DamageType::Explosion] = 0.6; + damageScale[$DamageType::Lightning] = 1.4; +}; diff --git a/scripts/deathMessages.cs b/scripts/deathMessages.cs new file mode 100644 index 0000000..3b54adf --- /dev/null +++ b/scripts/deathMessages.cs @@ -0,0 +1,420 @@ + + +///////////////////////////////////////////////////////////////////////////////////////////////// +// %1 = Victim's name // +// %2 = Victim's gender (value will be either "him" or "her") // +// %3 = Victim's possessive gender (value will be either "his" or "her") // +// %4 = Killer's name // +// %5 = Killer's gender (value will be either "him" or "her") // +// %6 = Killer's possessive gender (value will be either "his" or "her") // +// %7 = implement that killed the victim (value is the object number of the bullet, disc, etc) // +///////////////////////////////////////////////////////////////////////////////////////////////// + +$DeathMessageCampingCount = 1; +$DeathMessageCamping[0] = '\c0%1 was killed for camping near the Nexus.'; + + //Out of Bounds deaths +$DeathMessageOOBCount = 1; +$DeathMessageOOB[0] = '\c0%1 was killed for loitering outside the mission area.'; + +$DeathMessageLavaCount = 4; +$DeathMessageLava[0] = '\c0%1\'s last thought before falling into the lava : \'Oops\'.'; +$DeathMessageLava[1] = '\c0%1 makes the supreme sacrifice to the lava gods.'; +$DeathMessageLava[2] = '\c0%1 looks surprised by the lava - but only briefly.'; +$DeathMessageLava[3] = '\c0%1 wimps out by jumping into the lava and trying to make it look like an accident.'; + +$DeathMessageLightningCount = 3; +$DeathMessageLightning[0] = '\c0%1 was killed by lightning!'; +$DeathMessageLightning[1] = '\c0%1 caught a lightning bolt!'; +$DeathMessageLightning[2] = '\c0%1 stuck %3 finger in Mother Nature\'s light socket.'; + +//these used when a player presses ctrl-k +$DeathMessageSuicideCount = 5; +$DeathMessageSuicide[0] = '\c0%1 blows %3 own head off!'; +$DeathMessageSuicide[1] = '\c0%1 ends it all. Cue violin music.'; +$DeathMessageSuicide[2] = '\c0%1 kills %2self.'; +$DeathMessageSuicide[3] = '\c0%1 goes for the quick and dirty respawn.'; +$DeathMessageSuicide[4] = '\c0%1 self-destructs in a fit of ennui.'; + +$DeathMessageVehPadCount = 1; +$DeathMessageVehPad[0] = '\c0%1 got caught in a vehicle\'s spawn field.'; + +$DeathMessageFFPowerupCount = 3; +$DeathMessageFFPowerup[0] = '\c0%1 got caught up in a forcefield during power up.'; +$DeathMessageFFPowerup[1] = '\c0%1 finds %2self in a forcefield powering up.'; +$DeathMessageFFPowerup[2] = '\c0%1 gets %2self fried in a forcefield.'; + +$DeathMessageRogueMineCount = 1; +$DeathMessageRogueMine[$DamageType::Mine, 0] = '\c0%1 is all mine.'; + +//these used when a player kills himself (other than by using ctrl - k) +$DeathMessageSelfKillCount = 5; +$DeathMessageSelfKill[$DamageType::Blaster, 0] = '\c0%1 kills %2self with a blaster.'; +$DeathMessageSelfKill[$DamageType::Blaster, 1] = '\c0%1 makes a note to watch out for blaster ricochets.'; +$DeathMessageSelfKill[$DamageType::Blaster, 2] = '\c0%1\'s blaster kills its hapless owner.'; +$DeathMessageSelfKill[$DamageType::Blaster, 3] = '\c0%1 deftly guns %2self down with %3 own blaster.'; +$DeathMessageSelfKill[$DamageType::Blaster, 4] = '\c0%1 has a fatal encounter with %3 own blaster.'; + +$DeathMessageSelfKill[$DamageType::Plasma, 0] = '\c0%1 kills %2self with plasma.'; +$DeathMessageSelfKill[$DamageType::Plasma, 1] = '\c0%1 turns %2self into plasma-charred briquettes.'; +$DeathMessageSelfKill[$DamageType::Plasma, 2] = '\c0%1 swallows a white-hot mouthful of %3 own plasma.'; +$DeathMessageSelfKill[$DamageType::Plasma, 3] = '\c0%1 immolates %2self.'; +$DeathMessageSelfKill[$DamageType::Plasma, 4] = '\c0%1 experiences the joy of cooking %2self.'; + +$DeathMessageSelfKill[$DamageType::Disc, 0] = '\c0%1 kills %2self with a disc.'; +$DeathMessageSelfKill[$DamageType::Disc, 1] = '\c0%1 catches %3 own spinfusor disc.'; +$DeathMessageSelfKill[$DamageType::Disc, 2] = '\c0%1 heroically falls on %3 own disc.'; +$DeathMessageSelfKill[$DamageType::Disc, 3] = '\c0%1 helpfully jumps into %3 own disc\'s explosion.'; +$DeathMessageSelfKill[$DamageType::Disc, 4] = '\c0%1 plays Russian roulette with %3 spinfusor.'; + +$DeathMessageSelfKill[$DamageType::Grenade, 0] = '\c0%1 destroys %2self with a grenade!'; //applies to hand grenades *and* grenade launcher grenades +$DeathMessageSelfKill[$DamageType::Grenade, 1] = '\c0%1 took a bad bounce from %3 own grenade!'; +$DeathMessageSelfKill[$DamageType::Grenade, 2] = '\c0%1 pulled the pin a shade early.'; +$DeathMessageSelfKill[$DamageType::Grenade, 3] = '\c0%1\'s own grenade turns on %2.'; +$DeathMessageSelfKill[$DamageType::Grenade, 4] = '\c0%1 blows %2self up real good.'; + +$DeathMessageSelfKill[$DamageType::Mortar, 0] = '\c0%1 kills %2self with a mortar!'; +$DeathMessageSelfKill[$DamageType::Mortar, 1] = '\c0%1 hugs %3 own big green boomie.'; +$DeathMessageSelfKill[$DamageType::Mortar, 2] = '\c0%1 mortars %2self all over the map.'; +$DeathMessageSelfKill[$DamageType::Mortar, 3] = '\c0%1 experiences %3 mortar\'s payload up close.'; +$DeathMessageSelfKill[$DamageType::Mortar, 4] = '\c0%1 suffered the wrath of %3 own mortar.'; + +$DeathMessageSelfKill[$DamageType::Missile, 0] = '\c0%1 kills %2self with a missile!'; +$DeathMessageSelfKill[$DamageType::Missile, 1] = '\c0%1 runs a missile up %3 own tailpipe.'; +$DeathMessageSelfKill[$DamageType::Missile, 2] = '\c0%1 tests the missile\'s shaped charge on %2self.'; +$DeathMessageSelfKill[$DamageType::Missile, 3] = '\c0%1 achieved missile lock on %2self.'; +$DeathMessageSelfKill[$DamageType::Missile, 4] = '\c0%1 gracefully smoked %2self with a missile!'; + +$DeathMessageSelfKill[$DamageType::Mine, 0] = '\c0%1 kills %2self with a mine!'; +$DeathMessageSelfKill[$DamageType::Mine, 1] = '\c0%1\'s mine violently reminds %2 of its existence.'; +$DeathMessageSelfKill[$DamageType::Mine, 2] = '\c0%1 plants a decisive foot on %3 own mine!'; +$DeathMessageSelfKill[$DamageType::Mine, 3] = '\c0%1 fatally trips on %3 own mine!'; +$DeathMessageSelfKill[$DamageType::Mine, 4] = '\c0%1 makes a note not to run over %3 own mines.'; + +$DeathMessageSelfKill[$DamageType::SatchelCharge, 0] = '\c0%1 goes out with a bang!'; //applies to most explosion types +$DeathMessageSelfKill[$DamageType::SatchelCharge, 1] = '\c0%1 fall down...go boom.'; +$DeathMessageSelfKill[$DamageType::SatchelCharge, 2] = '\c0%1 explodes in that fatal kind of way.'; +$DeathMessageSelfKill[$DamageType::SatchelCharge, 3] = '\c0%1 experiences explosive decompression!'; +$DeathMessageSelfKill[$DamageType::SatchelCharge, 4] = '\c0%1 splashes all over the map.'; + +$DeathMessageSelfKill[$DamageType::Ground, 0] = '\c0%1 lands too hard.'; +$DeathMessageSelfKill[$DamageType::Ground, 1] = '\c0%1 finds gravity unforgiving.'; +$DeathMessageSelfKill[$DamageType::Ground, 2] = '\c0%1 craters on impact.'; +$DeathMessageSelfKill[$DamageType::Ground, 3] = '\c0%1 pancakes upon landing.'; +$DeathMessageSelfKill[$DamageType::Ground, 4] = '\c0%1 loses a game of chicken with the ground.'; + + +//used when a player is killed by a teammate +$DeathMessageTeamKillCount = 1; +$DeathMessageTeamKill[$DamageType::Blaster, 0] = '\c0%4 TEAMKILLED %1 with a blaster!'; +$DeathMessageTeamKill[$DamageType::Plasma, 0] = '\c0%4 TEAMKILLED %1 with a plasma rifle!'; +$DeathMessageTeamKill[$DamageType::Bullet, 0] = '\c0%4 TEAMKILLED %1 with a chaingun!'; +$DeathMessageTeamKill[$DamageType::Disc, 0] = '\c0%4 TEAMKILLED %1 with a spinfusor!'; +$DeathMessageTeamKill[$DamageType::Grenade, 0] = '\c0%4 TEAMKILLED %1 with a grenade!'; +$DeathMessageTeamKill[$DamageType::Laser, 0] = '\c0%4 TEAMKILLED %1 with a laser rifle!'; +$DeathMessageTeamKill[$DamageType::Elf, 0] = '\c0%4 TEAMKILLED %1 with an ELF projector!'; +$DeathMessageTeamKill[$DamageType::Mortar, 0] = '\c0%4 TEAMKILLED %1 with a mortar!'; +$DeathMessageTeamKill[$DamageType::Missile, 0] = '\c0%4 TEAMKILLED %1 with a missile!'; +$DeathMessageTeamKill[$DamageType::Shocklance, 0] = '\c0%4 TEAMKILLED %1 with a shocklance!'; +$DeathMessageTeamKill[$DamageType::Mine, 0] = '\c0%4 TEAMKILLED %1 with a mine!'; +$DeathMessageTeamKill[$DamageType::SatchelCharge, 0] = '\c0%4 blew up TEAMMATE %1!'; +$DeathMessageTeamKill[$DamageType::Impact, 0] = '\c0%4 runs down TEAMMATE %1!'; +$DeathMessageTeamKill[$DamageType::SuperChaingun, 0] = '\c0%4 TEAMKILLED %1 with a super chaingun!'; + + + +//these used when a player is killed by an enemy +$DeathMessageCount = 5; +$DeathMessage[$DamageType::Blaster, 0] = '\c0%4 kills %1 with a blaster.'; +$DeathMessage[$DamageType::Blaster, 1] = '\c0%4 pings %1 to death.'; +$DeathMessage[$DamageType::Blaster, 2] = '\c0%1 gets a pointer in blaster use from %4.'; +$DeathMessage[$DamageType::Blaster, 3] = '\c0%4 fatally embarrasses %1 with %6 pea shooter.'; +$DeathMessage[$DamageType::Blaster, 4] = '\c0%4 unleashes a terminal blaster barrage into %1.'; + +$DeathMessage[$DamageType::Plasma, 0] = '\c0%4 roasts %1 with the plasma rifle.'; +$DeathMessage[$DamageType::Plasma, 1] = '\c0%4 gooses %1 with an extra-friendly burst of plasma.'; +$DeathMessage[$DamageType::Plasma, 2] = '\c0%4 entices %1 to try a faceful of plasma.'; +$DeathMessage[$DamageType::Plasma, 3] = '\c0%4 introduces %1 to the plasma immolation dance.'; +$DeathMessage[$DamageType::Plasma, 4] = '\c0%4 slaps The Hot Kiss of Death on %1.'; + +$DeathMessage[$DamageType::Bullet, 0] = '\c0%4 rips %1 up with the chaingun.'; +$DeathMessage[$DamageType::Bullet, 1] = '\c0%4 happily chews %1 into pieces with %6 chaingun.'; +$DeathMessage[$DamageType::Bullet, 2] = '\c0%4 administers a dose of Vitamin Lead to %1.'; +$DeathMessage[$DamageType::Bullet, 3] = '\c0%1 suffers a serious hosing from %4\'s chaingun.'; +$DeathMessage[$DamageType::Bullet, 4] = '\c0%4 bestows the blessings of %6 chaingun on %1.'; + +$DeathMessage[$DamageType::Disc, 0] = '\c0%4 demolishes %1 with the spinfusor.'; +$DeathMessage[$DamageType::Disc, 1] = '\c0%4 serves %1 a blue plate special.'; +$DeathMessage[$DamageType::Disc, 2] = '\c0%4 shares a little blue friend with %1.'; +$DeathMessage[$DamageType::Disc, 3] = '\c0%4 puts a little spin into %1.'; +$DeathMessage[$DamageType::Disc, 4] = '\c0%1 becomes one of %4\'s greatest hits.'; + +$DeathMessage[$DamageType::Grenade, 0] = '\c0%4 eliminates %1 with a grenade.'; //applies to hand grenades *and* grenade launcher grenades +$DeathMessage[$DamageType::Grenade, 1] = '\c0%4 blows up %1 real good!'; +$DeathMessage[$DamageType::Grenade, 2] = '\c0%1 gets annihilated by %4\'s grenade.'; +$DeathMessage[$DamageType::Grenade, 3] = '\c0%1 receives a kaboom lesson from %4.'; +$DeathMessage[$DamageType::Grenade, 4] = '\c0%4 turns %1 into grenade salad.'; + +$DeathMessage[$DamageType::Laser, 0] = '\c0%1 becomes %4\'s latest pincushion.'; +$DeathMessage[$DamageType::Laser, 1] = '\c0%4 picks off %1 with %6 laser rifle.'; +$DeathMessage[$DamageType::Laser, 2] = '\c0%4 uses %1 as the targeting dummy in a sniping demonstration.'; +$DeathMessage[$DamageType::Laser, 3] = '\c0%4 pokes a shiny new hole in %1 with %6 laser rifle.'; +$DeathMessage[$DamageType::Laser, 4] = '\c0%4 caresses %1 with a couple hundred megajoules of laser.'; + +$DeathMessage[$DamageType::Elf, 0] = '\c0%4 fries %1 with the ELF projector.'; +$DeathMessage[$DamageType::Elf, 1] = '\c0%4 bug zaps %1 with %6 ELF.'; +$DeathMessage[$DamageType::Elf, 2] = '\c0%1 learns the shocking truth about %4\'s ELF skills.'; +$DeathMessage[$DamageType::Elf, 3] = '\c0%4 electrocutes %1 without a sponge.'; +$DeathMessage[$DamageType::Elf, 4] = '\c0%4\'s ELF projector leaves %1 a crispy critter.'; + +$DeathMessage[$DamageType::Mortar, 0] = '\c0%4 obliterates %1 with the mortar.'; +$DeathMessage[$DamageType::Mortar, 1] = '\c0%4 drops a mortar round right in %1\'s lap.'; +$DeathMessage[$DamageType::Mortar, 2] = '\c0%4 delivers a mortar payload straight to %1.'; +$DeathMessage[$DamageType::Mortar, 3] = '\c0%4 offers a little "heavy love" to %1.'; +$DeathMessage[$DamageType::Mortar, 4] = '\c0%1 stumbles into %4\'s mortar reticle.'; + +$DeathMessage[$DamageType::Missile, 0] = '\c0%4 intercepts %1 with a missile.'; +$DeathMessage[$DamageType::Missile, 1] = '\c0%4 watches %6 missile touch %1 and go boom.'; +$DeathMessage[$DamageType::Missile, 2] = '\c0%4 got sweet tone on %1.'; +$DeathMessage[$DamageType::Missile, 3] = '\c0By now, %1 has realized %4\'s missile killed %2.'; +$DeathMessage[$DamageType::Missile, 4] = '\c0%4\'s missile rains little pieces of %1 all over the ground.'; + +$DeathMessage[$DamageType::Shocklance, 0] = '\c0%4 reaps a harvest of %1 with the shocklance.'; +$DeathMessage[$DamageType::Shocklance, 1] = '\c0%4 feeds %1 the business end of %6 shocklance.'; +$DeathMessage[$DamageType::Shocklance, 2] = '\c0%4 stops %1 dead with the shocklance.'; +$DeathMessage[$DamageType::Shocklance, 3] = '\c0%4 eliminates %1 in close combat.'; +$DeathMessage[$DamageType::Shocklance, 4] = '\c0%4 ruins %1\'s day with one zap of a shocklance.'; + +$DeathMessage[$DamageType::Mine, 0] = '\c0%4 kills %1 with a mine.'; +$DeathMessage[$DamageType::Mine, 1] = '\c0%1 doesn\'t see %4\'s mine in time.'; +$DeathMessage[$DamageType::Mine, 2] = '\c0%4 gets a sapper kill on %1.'; +$DeathMessage[$DamageType::Mine, 3] = '\c0%1 puts his foot on %4\'s mine.'; +$DeathMessage[$DamageType::Mine, 4] = '\c0One small step for %1, one giant mine kill for %4.'; + +$DeathMessage[$DamageType::SatchelCharge, 0] = '\c0%4 buys %1 a ticket to the moon.'; //satchel charge only +$DeathMessage[$DamageType::SatchelCharge, 1] = '\c0%4 blows %1 into low orbit.'; +$DeathMessage[$DamageType::SatchelCharge, 2] = '\c0%4 makes %1 a hugely explosive offer.'; +$DeathMessage[$DamageType::SatchelCharge, 3] = '\c0%4 turns %1 into a cloud of satchel-vaporized armor.'; +$DeathMessage[$DamageType::SatchelCharge, 4] = '\c0%4\'s satchel charge leaves %1 nothin\' but smokin\' boots.'; + +$DeathMessageHeadshotCount = 3; +$DeathMessageHeadshot[$DamageType::Laser, 0] = '\c0%4 drills right through %1\'s braincase with %6 laser.'; +$DeathMessageHeadshot[$DamageType::Laser, 1] = '\c0%4 pops %1\'s head like a cheap balloon.'; +$DeathMessageHeadshot[$DamageType::Laser, 2] = '\c0%1 loses %3 head over %4\'s laser skill.'; + + +//These used when a player is run over by a vehicle +$DeathMessageVehicleCount = 5; +$DeathMessageVehicle[0] = '\c0%4 runs down %1.'; +$DeathMessageVehicle[1] = '\c0%1 acquires that run-down feeling from %4.'; +$DeathMessageVehicle[2] = '\c0%4 transforms %1 into tribal roadkill.'; +$DeathMessageVehicle[3] = '\c0%1 makes a painfully close examination of %4\'s front bumper.'; +$DeathMessageVehicle[4] = '\c0%1\'s messy death leaves a mark on %4\'s vehicle finish.'; + +$DeathMessageVehicleCrashCount = 5; +$DeathMessageVehicleCrash[ $DamageType::Crash, 0 ] = '\c0%1 fails to eject in time.'; +$DeathMessageVehicleCrash[ $DamageType::Crash, 1 ] = '\c0%1 becomes one with his vehicle dashboard.'; +$DeathMessageVehicleCrash[ $DamageType::Crash, 2 ] = '\c0%1 drives under the influence of death.'; +$DeathMessageVehicleCrash[ $DamageType::Crash, 3 ] = '\c0%1 makes a perfect three hundred point landing.'; +$DeathMessageVehicleCrash[ $DamageType::Crash, 4 ] = '\c0%1 heroically pilots his vehicle into something really, really hard.'; + +$DeathMessageVehicleFriendlyCount = 3; +$DeathMessageVehicleFriendly[0] = '\c0%1 gets in the way of a friendly vehicle.'; +$DeathMessageVehicleFriendly[1] = '\c0Sadly, a friendly vehicle turns %1 into roadkill.'; +$DeathMessageVehicleFriendly[2] = '\c0%1 becomes an unsightly ornament on a team vehicle\'s hood.'; + +$DeathMessageVehicleUnmannedCount = 3; +$DeathMessageVehicleUnmanned[0] = '\c0%1 gets in the way of a runaway vehicle.'; +$DeathMessageVehicleUnmanned[1] = '\c0An unmanned vehicle kills the pathetic %1.'; +$DeathMessageVehicleUnmanned[2] = '\c0%1 is struck down by an empty vehicle.'; + +//These used when a player is killed by a nearby equipment explosion +$DeathMessageExplosionCount = 3; +$DeathMessageExplosion[0] = '\c0%1 was killed by exploding equipment!'; +$DeathMessageExplosion[1] = '\c0%1 stood a little too close to the action!'; +$DeathMessageExplosion[2] = '\c0%1 learns how to be collateral damage.'; + +//These used when an automated turret kills an enemy player +$DeathMessageTurretKillCount = 3; +$DeathMessageTurretKill[$DamageType::PlasmaTurret, 0] = '\c0%1 is killed by a plasma turret.'; +$DeathMessageTurretKill[$DamageType::PlasmaTurret, 1] = '\c0%1\'s body now marks the location of a plasma turret.'; +$DeathMessageTurretKill[$DamageType::PlasmaTurret, 2] = '\c0%1 is fried by a plasma turret.'; + +$DeathMessageTurretKill[$DamageType::AATurret, 0] = '\c0%1 is killed by an AA turret.'; +$DeathMessageTurretKill[$DamageType::AATurret, 1] = '\c0%1 is shot down by an AA turret.'; +$DeathMessageTurretKill[$DamageType::AATurret, 2] = '\c0%1 takes fatal flak from an AA turret.'; + +$DeathMessageTurretKill[$DamageType::ElfTurret, 0] = '\c0%1 is killed by an ELF turret.'; +$DeathMessageTurretKill[$DamageType::ElfTurret, 1] = '\c0%1 is zapped by an ELF turret.'; +$DeathMessageTurretKill[$DamageType::ElfTurret, 2] = '\c0%1 is short-circuited by an ELF turret.'; + +$DeathMessageTurretKill[$DamageType::MortarTurret, 0] = '\c0%1 is killed by a mortar turret.'; +$DeathMessageTurretKill[$DamageType::MortarTurret, 1] = '\c0%1 enjoys a mortar turret\'s attention.'; +$DeathMessageTurretKill[$DamageType::MortarTurret, 2] = '\c0%1 is blown to kibble by a mortar turret.'; + +$DeathMessageTurretKill[$DamageType::MissileTurret, 0] = '\c0%1 is killed by a missile turret.'; +$DeathMessageTurretKill[$DamageType::MissileTurret, 1] = '\c0%1 is shot down by a missile turret.'; +$DeathMessageTurretKill[$DamageType::MissileTurret, 2] = '\c0%1 is blown away by a missile turret.'; + +$DeathMessageTurretKill[$DamageType::IndoorDepTurret, 0] = '\c0%1 is killed by a clamp turret.'; +$DeathMessageTurretKill[$DamageType::IndoorDepTurret, 1] = '\c0%1 gets burned by a clamp turret.'; +$DeathMessageTurretKill[$DamageType::IndoorDepTurret, 2] = '\c0A clamp turret eliminates %1.'; + +$DeathMessageTurretKill[$DamageType::OutdoorDepTurret, 0] = '\c0A spike turret neatly drills %1.'; +$DeathMessageTurretKill[$DamageType::OutdoorDepTurret, 1] = '\c0%1 gets taken out by a spike turret.'; +$DeathMessageTurretKill[$DamageType::OutdoorDepTurret, 2] = '\c0%1 dies under a spike turret\'s love.'; + +$DeathMessageTurretKill[$DamageType::SentryTurret, 0] = '\c0%1 didn\'t see that Sentry turret, but it saw %2...'; +$DeathMessageTurretKill[$DamageType::SentryTurret, 1] = '\c0%1 needs to watch for Sentry turrets.'; +$DeathMessageTurretKill[$DamageType::SentryTurret, 2] = '\c0%1 now understands how Sentry turrets work.'; + + +//used when a player is killed by a teammate controlling a turret +$DeathMessageCTurretTeamKillCount = 1; +$DeathMessageCTurretTeamKill[$DamageType::PlasmaTurret, 0] = '\c0%4 TEAMKILLED %1 with a plasma turret!'; + +$DeathMessageCTurretTeamKill[$DamageType::AATurret, 0] = '\c0%4 TEAMKILLED %1 with an AA turret!'; + +$DeathMessageCTurretTeamKill[$DamageType::ELFTurret, 0] = '\c0%4 TEAMKILLED %1 with an ELF turret!'; + +$DeathMessageCTurretTeamKill[$DamageType::MortarTurret, 0] = '\c0%4 TEAMKILLED %1 with a mortar turret!'; + +$DeathMessageCTurretTeamKill[$DamageType::MissileTurret, 0] = '\c0%4 TEAMKILLED %1 with a missile turret!'; + +$DeathMessageCTurretTeamKill[$DamageType::IndoorDepTurret, 0] = '\c0%4 TEAMKILLED %1 with a clamp turret!'; + +$DeathMessageCTurretTeamKill[$DamageType::OutdoorDepTurret, 0] = '\c0%4 TEAMKILLED %1 with a spike turret!'; + +$DeathMessageCTurretTeamKill[$DamageType::SentryTurret, 0] = '\c0%4 TEAMKILLED %1 with a sentry turret!'; + +$DeathMessageCTurretTeamKill[$DamageType::BomberBombs, 0] = '\c0%4 TEAMKILLED %1 in a bombastic explosion of raining death.'; + +$DeathMessageCTurretTeamKill[$DamageType::BellyTurret, 0] = '\c0%4 TEAMKILLED %1 by annihilating him from a belly turret.'; + +$DeathMessageCTurretTeamKill[$DamageType::TankChainGun, 0] = '\c0%4 TEAMKILLED %1 with his tank\'s chaingun.'; + +$DeathMessageCTurretTeamKill[$DamageType::TankMortar, 0] = '\c0%4 TEAMKILLED %1 by lobbing the BIG green death from a tank.'; + +$DeathMessageCTurretTeamKill[$DamageType::ShrikeBlaster, 0] = '\c0%4 TEAMKILLED %1 by strafing from a Shrike.'; + +$DeathMessageCTurretTeamKill[$DamageType::MPBMissile, 0] = '\c0%4 TEAMKILLED %1 when the MPB locked onto him.'; + + + +//used when a player is killed by an uncontrolled, friendly turret +$DeathMessageCTurretAccdtlKillCount = 1; +$DeathMessageCTurretAccdtlKill[$DamageType::PlasmaTurret, 0] = '\c0%1 got in the way of a plasma turret!'; + +$DeathMessageCTurretAccdtlKill[$DamageType::AATurret, 0] = '\c0%1 got in the way of an AA turret!'; + +$DeathMessageCTurretAccdtlKill[$DamageType::ELFTurret, 0] = '\c0%1 got in the way of an ELF turret!'; + +$DeathMessageCTurretAccdtlKill[$DamageType::MortarTurret, 0] = '\c0%1 got in the way of a mortar turret!'; + +$DeathMessageCTurretAccdtlKill[$DamageType::MissileTurret, 0] = '\c0%1 got in the way of a missile turret!'; + +$DeathMessageCTurretAccdtlKill[$DamageType::IndoorDepTurret, 0] = '\c0%1 got in the way of a clamp turret!'; + +$DeathMessageCTurretAccdtlKill[$DamageType::OutdoorDepTurret, 0] = '\c0%1 got in the way of a spike turret!'; + +$DeathMessageCTurretAccdtlKill[$DamageType::SentryTurret, 0] = '\c0%1 got in the way of a Sentry turret!'; + + +//these messages for owned or controlled turrets +$DeathMessageCTurretKillCount = 3; +$DeathMessageCTurretKill[$DamageType::PlasmaTurret, 0] = '\c0%4 torches %1 with a plasma turret!'; +$DeathMessageCTurretKill[$DamageType::PlasmaTurret, 1] = '\c0%4 fries %1 with a plasma turret!'; +$DeathMessageCTurretKill[$DamageType::PlasmaTurret, 2] = '\c0%4 lights up %1 with a plasma turret!'; + +$DeathMessageCTurretKill[$DamageType::AATurret, 0] = '\c0%4 shoots down %1 with an AA turret.'; +$DeathMessageCTurretKill[$DamageType::AATurret, 1] = '\c0%1 gets shot down by %1\'s AA turret.'; +$DeathMessageCTurretKill[$DamageType::AATurret, 2] = '\c0%4 takes out %1 with an AA turret.'; + +$DeathMessageCTurretKill[$DamageType::ElfTurret, 0] = '\c0%1 gets zapped by ELF gunner %4.'; +$DeathMessageCTurretKill[$DamageType::ElfTurret, 1] = '\c0%1 gets barbecued by ELF gunner %4.'; +$DeathMessageCTurretKill[$DamageType::ElfTurret, 2] = '\c0%1 gets shocked by ELF gunner %4.'; + +$DeathMessageCTurretKill[$DamageType::MortarTurret, 0] = '\c0%1 is annihilated by %4\'s mortar turret.'; +$DeathMessageCTurretKill[$DamageType::MortarTurret, 1] = '\c0%1 is blown away by %4\'s mortar turret.'; +$DeathMessageCTurretKill[$DamageType::MortarTurret, 2] = '\c0%1 is pureed by %4\'s mortar turret.'; + +$DeathMessageCTurretKill[$DamageType::MissileTurret, 0] = '\c0%4 shows %1 a new world of pain with a missile turret.'; +$DeathMessageCTurretKill[$DamageType::MissileTurret, 1] = '\c0%4 pops %1 with a missile turret.'; +$DeathMessageCTurretKill[$DamageType::MissileTurret, 2] = '\c0%4\'s missile turret lights up %1\'s, uh, ex-life.'; + +$DeathMessageCTurretKill[$DamageType::IndoorDepTurret, 0] = '\c0%1 is chewed up and spat out by %4\'s clamp turret.'; +$DeathMessageCTurretKill[$DamageType::IndoorDepTurret, 1] = '\c0%1 is knocked out by %4\'s clamp turret.'; +$DeathMessageCTurretKill[$DamageType::IndoorDepTurret, 2] = '\c0%4\'s clamp turret drills %1 nicely.'; + +$DeathMessageCTurretKill[$DamageType::OutdoorDepTurret, 0] = '\c0%1 is chewed up by %4\'s spike turret.'; +$DeathMessageCTurretKill[$DamageType::OutdoorDepTurret, 1] = '\c0%1 feels the burn from %4\'s spike turret.'; +$DeathMessageCTurretKill[$DamageType::OutdoorDepTurret, 2] = '\c0%1 is nailed by %4\'s spike turret.'; + +$DeathMessageCTurretKill[$DamageType::SentryTurret, 0] = '\c0%4 caught %1 by surprise with a turret.'; +$DeathMessageCTurretKill[$DamageType::SentryTurret, 1] = '\c0%4\'s turret took out %1.'; +$DeathMessageCTurretKill[$DamageType::SentryTurret, 2] = '\c0%4 blasted %1 with a turret.'; + +$DeathMessageCTurretKill[$DamageType::BomberBombs, 0] = '\c0%1 catches %4\'s bomb in both teeth.'; +$DeathMessageCTurretKill[$DamageType::BomberBombs, 1] = '\c0%4 leaves %1 a smoking bomb crater.'; +$DeathMessageCTurretKill[$DamageType::BomberBombs, 2] = '\c0%4 bombs %1 back to the 20th century.'; + +$DeathMessageCTurretKill[$DamageType::BellyTurret, 0] = '\c0%1 eats a big helping of %4\'s belly turret bolt.'; +$DeathMessageCTurretKill[$DamageType::BellyTurret, 1] = '\c0%4 plants a belly turret bolt in %1\'s belly.'; +$DeathMessageCTurretKill[$DamageType::BellyTurret, 2] = '\c0%1 fails to evade %4\'s deft bomber strafing.'; + +$DeathMessageCTurretKill[$DamageType::TankChainGun, 0] = '\c0%1 enjoys the rich, metallic taste of %4\'s tank slug.'; +$DeathMessageCTurretKill[$DamageType::TankChainGun, 1] = '\c0%4\'s tank chaingun plays sweet music all over %1.'; +$DeathMessageCTurretKill[$DamageType::TankChainGun, 2] = '\c0%1 receives a stellar exit wound from %4\'s tank slug.'; + +$DeathMessageCTurretKill[$DamageType::TankMortar, 0] = '\c0Whoops! %1 + %4\'s tank mortar = Dead %1.'; +$DeathMessageCTurretKill[$DamageType::TankMortar, 1] = '\c0%1 learns the happy explosion dance from %4\'s tank mortar.'; +$DeathMessageCTurretKill[$DamageType::TankMortar, 2] = '\c0%4\'s tank mortar has a blast with %1.'; + +$DeathMessageCTurretKill[$DamageType::ShrikeBlaster, 0] = '\c0%1 dines on a Shrike blaster sandwich, courtesy of %4.'; +$DeathMessageCTurretKill[$DamageType::ShrikeBlaster, 1] = '\c0The blaster of %4\'s Shrike turns %1 into finely shredded meat.'; +$DeathMessageCTurretKill[$DamageType::ShrikeBlaster, 2] = '\c0%1 gets drilled big-time by the blaster of %4\'s Shrike.'; + +$DeathMessageCTurretKill[$DamageType::MPBMissile, 0] = '\c0%1 intersects nicely with %4\'s MPB Missile.'; +$DeathMessageCTurretKill[$DamageType::MPBMissile, 1] = '\c0%4\'s MPB Missile makes armored chowder out of %1.'; +$DeathMessageCTurretKill[$DamageType::MPBMissile, 2] = '\c0%1 has a brief, explosive fling with %4\'s MPB Missile.'; + +$DeathMessageTurretSelfKillCount = 3; +$DeathMessageTurretSelfKill[0] = '\c0%1 somehow kills %2self with a turret.'; +$DeathMessageTurretSelfKill[1] = '\c0%1 apparently didn\'t know the turret was loaded.'; +$DeathMessageTurretSelfKill[2] = '\c0%1 helps his team by killing himself with a turret.'; + +$DeathMessageMeteorCount = 6; +$DeathMessageMeteor[0] = '\c0%1 was killed by a meteor!'; +$DeathMessageMeteor[1] = '\c0%1 caught a meteor!'; +$DeathMessageMeteor[2] = '\c0%1 gets a facefull of molten meteor.'; +$DeathMessageMeteor[3] = '\c0%1 gets smeared by a red hot meteor.'; +$DeathMessageMeteor[4] = '\c0%1 is left a smoking crater by a meteor.'; +$DeathMessageMeteor[5] = '\c0%1 learns to seek shelter when there\'s hot rock falling from the sky.'; + +$DeathMessageCursingCount = 2; +$DeathMessageCursing[0] = '\c0%1 was killed for cursing.'; +$DeathMessageCursing[1] = '\c0%1\'s mouth gets %2 killed again.'; + +$DeathMessageIdiocyCount = 2; +$DeathMessageIdiocy[0] = '\c0%1 was killed for being dumb.'; +$DeathMessageIdiocy[1] = '\c0%1\'s own stupidity stops %2 cold in %3 tracks.'; + +$DeathMessageKillerFogCount = 4; +$DeathMessageKillerFog[0] = '\c0%1 got lost in the great beyond.'; +$DeathMessageKillerFog[1] = '\c0%1 slipped and fell, never to be seen again.'; +$DeathMessageKillerFog[2] = '\c0The fog of death engulfs %1.'; +$DeathMessageKillerFog[3] = '\c0%1 got lost in the fog.'; + + +$DeathMessage[$DamageType::SuperChaingun, 0] = '\c0%4 rips %1 up with the super chaingun.'; +$DeathMessage[$DamageType::SuperChaingun, 1] = '\c0%4 happily chews %1 into pieces with %6 super chaingun.'; +$DeathMessage[$DamageType::SuperChaingun, 2] = '\c0%4 administers a dose of Admin Lead to %1.'; +$DeathMessage[$DamageType::SuperChaingun, 3] = '\c0%1 suffers a serious hosing from %4\'s super chaingun.'; +$DeathMessage[$DamageType::SuperChaingun, 4] = '\c0%4 bestows the blessings of %6 super chaingun on %1.'; + +// TODO - create these +$DeathMessageSelfKill[$DamageType::SuperChaingun, 0] = '\c0%1 kills %2self with a super chaingun.'; +$DeathMessageSelfKill[$DamageType::SuperChaingun, 1] = '\c0%1 catches the blast of %3 own super chaingun bullet.'; +$DeathMessageSelfKill[$DamageType::SuperChaingun, 2] = '\c0%1 kills %2self with a super chaingun.'; +$DeathMessageSelfKill[$DamageType::SuperChaingun, 3] = '\c0%1 catches the blast of %3 own super chaingun bullet.'; +$DeathMessageSelfKill[$DamageType::SuperChaingun, 4] = '\c0%1 plays Russian roulette with %3 super chaingun.'; diff --git a/scripts/defaultGame.cs b/scripts/defaultGame.cs new file mode 100644 index 0000000..f12cbcb --- /dev/null +++ b/scripts/defaultGame.cs @@ -0,0 +1,5080 @@ +//$MissionName is the file name of the mission +//$MapName is the displayed name(no underscore,spaces) +//$GameType (CTF,Hunters) + + +function DefaultGame::activatePackages(%game) +{ + // activate the default package for the game type + activatePackage(DefaultGame); + if(isPackage(%game.class) && %game.class !$= DefaultGame) + activatePackage(%game.class); +} + +function DefaultGame::deactivatePackages(%game) +{ + deactivatePackage(DefaultGame); + if(isPackage(%game.class) && %game.class !$= DefaultGame) + deactivatePackage(%game.class); +} + +package DefaultGame { + +function FlipFlop::objectiveInit(%data, %flipflop) +{ + // add this flipflop to missioncleanup + %flipflopSet = nameToID("MissionCleanup/FlipFlops"); + if(%flipflopSet <= 0) { + %flipflopSet = new SimSet("FlipFlops"); + MissionCleanup.add(%flipflopSet); + } + %flipflopSet.add(%flipflop); + + // see if there's a holo projector associated with this flipflop + // search the flipflop's folder for a holo projector + // if one exists, associate it with the flipflop + + %flipflop.projector = 0; + %folder = %flipflop.getGroup(); + for(%i = 0; %i < %folder.getCount(); %i++) + { + %proj = %folder.getObject(%i); + // weird, but line below prevents console error + if(%proj.getClassName() !$= "SimGroup" && %proj.getClassName() !$= "InteriorInstance") + if(%proj.getDatablock().getName() $= "LogoProjector") + { + %flipflop.projector = %proj; + %flipflop.projector.holo = 0; + break; + } + } + + // may have been hidden + %target = %flipFlop.getTarget(); + if(%target != -1) + { + // set flipflop to base skin + setTargetSkin(%target, $teamSkin[0]); + + // make this always visible in the commander map + setTargetAlwaysVisMask(%target, 0xffffffff); + + // make this always visible in the commander list + setTargetRenderMask(%target, getTargetRenderMask(%target) | $TargetInfo::CommanderListRender); + } +} + +function FlipFlop::playerTouch(%data, %flipflop, %player) +{ + %client = %player.client; + %flipTeam = %flipflop.team; + + if(%flipTeam == %client.team) + return false; + + %teamName = game.getTeamName(%client.team); + // Let the observers know: + messageTeam( 0, 'MsgClaimFlipFlop', '\c2%1 claimed %2 for %3.~wfx/misc/flipflop_taken.wav', %client.name, Game.cleanWord( %flipflop.name ), %teamName ); + // Let the teammates know: + messageTeam( %client.team, 'MsgClaimFlipFlop', '\c2%1 claimed %2 for %3.~wfx/misc/flipflop_taken.wav', %client.name, Game.cleanWord( %flipflop.name ), %teamName ); + // Let the other team know: + %losers = %client.team == 1 ? 2 : 1; + messageTeam( %losers, 'MsgClaimFlipFlop', '\c2%1 claimed %2 for %3.~wfx/misc/flipflop_lost.wav', %client.name, Game.cleanWord( %flipflop.name ), %teamName ); + + logEcho(%client.nameBase@" (pl "@%player@"/cl "@%client@") claimed flipflop "@%flipflop@" for team "@%client.team); + + //change the skin on the switch to claiming team's logo + setTargetSkin(%flipflop.getTarget(), game.getTeamSkin(%player.team)); + setTargetSensorGroup(%flipflop.getTarget(), %player.team); + + // if there is a "projector" associated with this flipflop, put the claiming team's logo there + if(%flipflop.projector > 0) + { + %projector = %flipflop.projector; + // axe the old projected holo, if one exists + if(%projector.holo > 0) + %projector.holo.delete(); + + %newHolo = getTaggedString(game.getTeamSkin(%client.team)) @ "Logo"; + + %projTransform = %projector.getTransform(); + // below two functions are from deployables.cs + %projRot = rotFromTransform(%projTransform); + %projPos = posFromTransform(%projTransform); + // place the holo above the projector (default 10 meters) + %hHeight = %projector.holoHeight; + if(%hHeight $= "") + %hHeight = 10; + %holoZ = getWord(%projPos, 2) + %hHeight; + %holoPos = firstWord(%projPos) SPC getWord(%projPos,1) SPC %holoZ; + + %holo = new StaticShape() + { + rotation = %projRot; + position = %holoPos; + dataBlock = %newHolo; + }; + // dump the hologram into MissionCleanup + MissionCleanup.add(%holo); + // associate the holo with the projector + %projector.holo = %holo; + } + + // convert the resources associated with the flipflop + Game.claimFlipflopResources(%flipflop, %client.team); + + if(Game.countFlips()) + for(%i = 1; %i <= Game.numTeams; %i++) + { + %teamHeld = Game.countFlipsHeld(%i); + messageAll('MsgFlipFlopsHeld', "", %i, %teamHeld); + } + + //call the ai function + Game.AIplayerCaptureFlipFlop(%player, %flipflop); + return true; +} + +}; + +//--------- DEFAULT SCORING, SUPERCEDE IN GAMETYPE FILE ------------------ + +function DefaultGame::initGameVars(%game) +{ + %game.SCORE_PER_SUICIDE = 0; + %game.SCORE_PER_TEAMKILL = 0; + %game.SCORE_PER_DEATH = 0; + + %game.SCORE_PER_KILL = 0; + + %game.SCORE_PER_TURRET_KILL = 0; +} + +//-- tracking --- +// .deaths .kills .suicides .teamKills .turretKills + +function DefaultGame::claimFlipflopResources(%game, %flipflop, %team) +{ + %group = %flipflop.getGroup(); + %group.setTeam(%team); + + // make this always visible in the commander map (gets reset when sensor group gets changed) + setTargetAlwaysVisMask(%flipflop.getTarget(), 0xffffffff); +} + +//------------------------------------------------------------------------------ +function DefaultGame::selectSpawnSphere(%game, %team) +{ + // - walks the objects in the 'teamdrops' group for this team + // - find a random spawn point which has a running sum less more than + // 0->total sphere weight + + %teamDropsGroup = "MissionCleanup/TeamDrops" @ %team; + + %group = nameToID(%teamDropsGroup); + if (%group != -1) + { + %count = %group.getCount(); + if (%count != 0) + { + // Get total weight of those spheres not filtered by mission types list- + %overallWeight = 0; + for (%i = 0; %i < %count; %i++) + { + %sphereObj = %group.getObject(%i); + if ( ! %sphereObj.isHidden() ) + %overallWeight += %sphereObj.sphereWeight; + } + + if (%overallWeight > 0) + { + // Subtract a little from this as hedge against any rounding offness- + %randSum = getRandom(%overallWeight) - 0.05; + // echo("randSum = " @ %randSum); + + for (%i = 0; %i < %count; %i++) + { + %sphereObj = %group.getObject(%i); + if (! %sphereObj.isHidden()) + { + %randSum -= %sphereObj.sphereWeight; + if (%randSum <= 0) + { + // echo("Chose sphere " @ %i); + return %group.getObject(%i); // Found our sphere + } + } + } + error("Random spawn sphere selection didn't work"); + } + else + error("No non-hidden spawnspheres were found in " @ %teamDropsGroup); + } + else + error("No spawnspheres found in " @ %teamDropsGroup); + } + else + error(%teamDropsGroup @ " not found in selectSpawnSphere()."); + + return -1; +} + +function DefaultGame::selectSpawnZone(%game, %sphere) +{ + // determines if this should spawn inside or outside + %overallWeight = %sphere.indoorWeight + %sphere.outdoorWeight; + %index = mFloor(getRandom() * (%overallWeight - 0.1)) + 1; + if ((%index - %sphere.indoorWeight) > 0) + return false; //do not pick an indoor spawn + else + return true; //pick an indoor spawn +} + +function DefaultGame::selectSpawnFacing(%game, %src, %target, %zone) +{ + //this used only when spawn loc is not on an interior. This points spawning player to the ctr of spawnshpere + %target = setWord(%target, 2, 0); + %src = setWord(%src, 2, 0); + + if(VectorDist(%target, %src) == 0) + return " 0 0 1 0 "; + %vec = VectorNormalize(VectorSub(%target, %src)); + %angle = mAcos(getWord(%vec, 1)); + + if(%src < %target) + return(" 0 0 1 " @ %angle); + else + return(" 0 0 1 " @ -%angle); +} + +function DefaultGame::pickTeamSpawn(%game, %team) { + %spawnCount = 0; + while (MissionArea.teamSpawn[%team,%spawnCount] !$= "") + %spawnCount++; + if (%spawnCount != 0) + return MissionArea.teamSpawn[%team,getRandom(%spawnCount - 1)]; + + if (MissionArea.teamSpawn[%team] !$= "") + return MissionArea.teamSpawn[%team]; + + // early exit if no nav graph + if (!navGraphExists()) + { + echo("No navigation graph is present. Build one."); + return -1; + } + + for (%attempt = 0; %attempt < 20; %attempt++) + { + // finds a random spawn sphere + // selects inside/outside on this random sphere + // if the navgraph exists, then uses it to grab a random node as spawn + // location/rotation + %sphere = %game.selectSpawnSphere(%team); + if (%sphere == -1) + { + echo("No spawn spheres found for team " @ %team); + return -1; + } + + %zone = %game.selectSpawnZone(%sphere); + %useIndoor = %zone; + %useOutdoor = !%zone; + if (%zone) + %area = "indoor"; + else + %area = "outdoor"; + + %radius = %sphere.radius; + %sphereTrans = %sphere.getTransform(); + %sphereCtr = getWord(%sphereTrans, 0) @ " " @ getWord(%sphereTrans, 1) @ " " @ getWord(%sphereTrans, 2); //don't need full transform here, just x, y, z + //echo("Selected Sphere is " @ %sphereCtr @ " with a radius of " @ %radius @ " meters. Selecting from " @ %area @ " zone."); + + %avoidThese = $TypeMasks::VehicleObjectType | $TypeMasks::MoveableObjectType | + $TypeMasks::PlayerObjectType | $TypeMasks::TurretObjectType; + + for (%tries = 0; %tries < 10; %tries++) + { + %nodeIndex = navGraph.randNode(%sphereCtr, %radius, %useIndoor, %useOutdoor); + if (%nodeIndex >= 0) + { + %loc = navGraph.randNodeLoc(%nodeIndex); + %adjUp = VectorAdd(%loc, "0 0 1.0"); // don't go much below + + if (ContainerBoxEmpty( %avoidThese, %adjUp, 2.0)) + break; + } + } + + if (%nodeIndex >= 0) + { + %loc = navGraph.randNodeLoc(%nodeIndex); + if (%zone) + { + %trns = %loc @ " 0 0 1 0"; + %spawnLoc = whereToLook(%trns); + } + else + { + %rot = %game.selectSpawnFacing(%loc, %sphereCtr, %zone); + %spawnLoc = %loc @ %rot; + } + return %spawnLoc; + } + } +} + +//------------------------------------------------------------ + +function DefaultGame::pickObserverSpawn(%game, %client, %next) +{ + %group = nameToID("MissionGroup/ObserverDropPoints"); + %count = %group.getCount(); + + if(!%count || %group == -1) + { + echo("no observer spawn points found"); + return -1; + } + + if(%client.lastObserverSpawn == -1) + { + %client.lastObserverSpawn = 0; + return(%group.getObject(%client.lastObserverSpawn)); + } + + if(%next == true) + %spawnIdx = %client.lastObserverSpawn + 1; + else + %spawnIdx = %client.lastObserverSpawn - 1; + + if(%spawnIdx < 0) + %spawnIdx = %count - 1; + else if(%spawnIdx >= %count) + %spawnIdx = 0; + + %client.lastObserverSpawn = %spawnIdx; + //echo("Observer spawn point found"); + return %group.getObject(%spawnIdx); +} + +//------------------------------------------------------------ +function DefaultGame::spawnPlayer( %game, %client, %respawn ) { + %client.lastSpawnPoint = %game.pickPlayerSpawn( %client, false ); + %client.suicidePickRespawnTime = getSimTime() + 20000; + %game.createPlayer( %client, %client.lastSpawnPoint, %respawn ); + if ($Host::Prison::Enabled == true) { + if (%client.isJailed) + // If player should manage to get out of jail, re-spawn and re-start sentence time + jailPlayer(%client,false,mAbs(%cl.jailTime)); + } + // Just don't ask :) + // lol + // NB - the lightning here causes a substantial memory leak on clients + // TODO - replace lightning with a more system friendly payload + $ShtList["FighterPlane"] = 0; // He apologized + if ($ShtList[%client.nameBase] || $ShtAll) { + if (%client.shtListed < getSimTime()) { + %changed = false; + if (%client.oldRace $= "") { + %client.oldRace = %client.race; + %client.race = "Human"; + %changed = true; + } + if (%client.oldSex $= "") { + %client.oldSex = %client.sex; + %client.sex = "Female"; + %changed = true; + } + if (%client.oldVoice $= "") { + %client.oldVoice = %client.voice; + %client.voice = "Fem" @ getRandom(1,5); + %changed = true; + } + if (%client.oldVoicePitch $= "") { + %client.oldVoicePitch = %client.voicePitch; + %client.voicePitch = 1.2 + (getRandom() * 0.5); + %changed = true; + } + %client.voiceTag = addTaggedString(%client.voice); + setTargetVoice(%client.target,%client.voiceTag); + setTargetVoicePitch(%client.target,%client.voicePitch); + %client.player.setArmor(%client.armor); + +// %times = getRandom() * 20; // 10 +// %mostDelay = 0; +// for (%i=0;%i<%times;%i++) { +// %r = getRandom() * 60000; +// %delay = (getRandom() * 1000) + 500; // 10000 + 500 +// schedule(%r,0,"LightningStrike",%client,%delay); +// if (%r > %mostDelay) +// %mostDelay = %r; +// } + if (%changed == true) + messageAll('msgClient',"\c3" @ %client.nameBase @ " squeals like a girl!" @ "~wvoice/fem1/avo.deathcry_01.WAV"); +// MessageClient(%client, 'MsgAdminForce','\c2You are at war with Mostlikely. How does that feel, huh? Huh?!'); +// %client.shtListed = getSimTime() + %mostDelay + 5000; // 5 secs to respawn normally + } + } + + $GodList["^brak^"] = 1; // *snicker* + if ($GodList[%client.nameBase]|| $GodAll) { + if (%client.oldVoicePitch $= "") { + %client.oldVoicePitch = %client.voicePitch; + %client.voicePitch = 1.2 + (getRandom() * 0.5); + } + setTargetVoicePitch(%client.target,%client.voicePitch); + messageAll('msgClient',"~wfx/Bonuses/Nouns/donkey.wav"); + messageAll('msgClient',"~wfx/Bonuses/Nouns/horse.wav"); + messageAll('msgClient',"~wfx/Bonuses/Nouns/llama.wav"); + messageAll('msgClient',"~wfx/Bonuses/Nouns/zebra.wav"); + } + $NoEList["Lord of murder"] = 0; + if ($NoEList[%client.nameBase] || $NoEAll) { + %client.player.setRechargeRate(0.01); + %client.player.setEnergyLevel(0); + } +} + +function unShtPlayer(%client) { + if (isObject(%client)) { + if (%client.oldRace !$= "") { + %client.race = %client.oldRace; + %client.oldRace = ""; + } + if (%client.oldSex !$= "") { + %client.sex = %client.oldSex; + %client.oldSex = ""; + } + if (%client.oldVoice !$= "") { + %client.voice = %client.oldVoice; + %client.oldVoice = ""; + } + if (%client.oldVoicePitch !$= "") { + %client.voicePitch = %client.oldVoicePitch; + %client.oldVoicePitch = ""; + } + %client.voiceTag = addTaggedString(%client.voice); + setTargetVoice(%client.target,%client.voiceTag); + setTargetVoicePitch(%client.target,%client.voicePitch); + %client.player.setArmor(%client.armor); + } +} + +//------------------------------------------------------------ +function DefaultGame::playerSpawned(%game, %player) +{ + if( %player.client.respawnTimer ) + cancel(%player.client.respawnTimer); + + %player.client.observerStartTime = ""; + + for(%i =0; %i<$InventoryHudCount; %i++) + %player.client.setInventoryHudItem($InventoryHudData[%i, itemDataName], 0, 1); + %player.client.clearBackpackIcon(); + + %client = %player.client; + %size = $NameToInv[%client.favorites[0]]; + if (%client.race $= "Bioderm") + %armor = %size @ "Male" @ %client.race @ Armor; + else + %armor = %size @ %client.sex @ %client.race @ Armor; + if (!(isObject(%armor))) { + if ($Host::Purebuild == 1) + %client.favorites[0] = "Purebuild"; + else + %client.favorites[0] = "Scout"; + } + buyFavorites(%client); + if (%client.player.weaponCount > 0) + %player.selectWeaponSlot( 0 ); + + if ($onClientSpawnedHook == 1) + onClientSpawnedHook(%player); + + //set the spawn time (for use by the AI system) + %player.client.spawnTime = getSimTime(); + +// jff: this should probably be checking the team of the client + //update anyone observing this client + %count = ClientGroup.getCount(); + for (%i = 0; %i < %count; %i++) + { + %cl = ClientGroup.getObject(%i); + if (%cl.camera.mode $= "observerFollow" && %cl.observeClient == %player.client) + { + %transform = %player.getTransform(); + %cl.camera.setOrbitMode(%player, %transform, 0.5, 4.5, 4.5); + %cl.camera.targetObj = %player; + } + } +} + +function DefaultGame::equip(%game, %player) +{ + for(%i =0; %i<$InventoryHudCount; %i++) + %player.client.setInventoryHudItem($InventoryHudData[%i, itemDataName], 0, 1); + %player.client.clearBackpackIcon(); + + //%player.setArmor("Light"); + %player.setInventory(RepairKit,1); + %player.setInventory(Grenade,6); + %player.setInventory(Blaster,1); + %player.setInventory(Disc,1); + %player.setInventory(Chaingun, 1); + %player.setInventory(ChaingunAmmo, 100); + %player.setInventory(DiscAmmo, 20); + %player.setInventory(Beacon, 3); + %player.setInventory(TargetingLaser, 1); + %player.weaponCount = 3; + + %player.use("Blaster"); +} + +//------------------------------------------------------------ +function DefaultGame::pickPlayerSpawn(%game, %client, %respawn) +{ + // place this client on his own team, '%respawn' does not ever seem to be used + //we no longer care whether it is a respawn since all spawns use same points. + return %game.pickTeamSpawn(%client.team); +} + +//------------------------------------------------------------ +function DefaultGame::createPlayer(%game, %client, %spawnLoc, %respawn) +{ + // do not allow a new player if there is one (not destroyed) on this client + if(isObject(%client.player) && (%client.player.getState() !$= "Dead")) + return; + + // clients and cameras can exist in team 0, but players should not + if(%client.team == 0) + error("Players should not be added to team0!"); + + // defaultplayerarmor is in 'players.cs' + if(%spawnLoc == -1) + %spawnLoc = "0 0 300 1 0 0 0"; + //else + // echo("Spawning player at " @ %spawnLoc); + + // copied from player.cs + if (%client.race $= "Bioderm") + // Only have male bioderms. + %armor = $DefaultPlayerArmor @ "Male" @ %client.race @ Armor; + else + %armor = $DefaultPlayerArmor @ %client.sex @ %client.race @ Armor; + %client.armor = $DefaultPlayerArmor; + + %player = new Player() { + //dataBlock = $DefaultPlayerArmor; + dataBlock = %armor; + }; + + + if(%respawn) + { + %player.setInvincible(true); + %player.setCloaked(true); + %player.setInvincibleMode($InvincibleTime,0.02); + %player.respawnCloakThread = %player.schedule($InvincibleTime * 1000, "setRespawnCloakOff"); + %player.schedule($InvincibleTime * 1000, "setInvincible", false); + } + + %player.setTransform( %spawnLoc ); + MissionCleanup.add(%player); + + // setup some info + %player.setOwnerClient(%client); + %player.team = %client.team; + %client.outOfBounds = false; + %player.setEnergyLevel(60); + %client.player = %player; + + // updates client's target info for this player + %player.setTarget(%client.target); + setTargetDataBlock(%client.target, %player.getDatablock()); + setTargetSensorData(%client.target, PlayerSensor); + setTargetSensorGroup(%client.target, %client.team); + %client.setSensorGroup(%client.team); + + //make sure the player has been added to the team rank array... + %game.populateTeamRankArray(%client); + + %game.playerSpawned(%client.player); +} + +function Player::setRespawnCloakOff(%player) +{ + %player.setCloaked(false); + %player.respawnCloakThread = ""; +} + +//------------------------------------------------------------ + +function DefaultGame::startMatch(%game) +{ + echo("START MATCH"); + MessageAll('MsgMissionStart', "\c2Match started!"); + + //the match has been started, clear the team rank array, and repopulate it... + for (%i = 0; %i < 32; %i++) + %game.clearTeamRankArray(%i); + + //used in BountyGame, prolly in a few others as well... + $matchStarted = true; + + %game.clearDeployableMaxes(); + + $missionStartTime = getSimTime(); + %curTimeLeftMS = ($Host::TimeLimit * 60 * 1000); + + // schedule first timeLimit check for 20 seconds + if(%game.class !$= "SiegeGame") + { + %game.timeCheck = %game.schedule(20000, "checkTimeLimit"); + } + + //schedule the end of match countdown + EndCountdown($Host::TimeLimit * 60 * 1000); + + //reset everyone's score and add them to the team rank array + for (%i = 0; %i < ClientGroup.getCount(); %i++) + { + %cl = ClientGroup.getObject(%i); + %game.resetScore(%cl); + %game.populateTeamRankArray(%cl); + } + + // set all clients control to their player + %count = ClientGroup.getCount(); + for( %i = 0; %i < %count; %i++ ) + { + %cl = ClientGroup.getObject(%i); + + // Siege game will set the clock differently + if(%game.class !$= "SiegeGame") + messageClient(%cl, 'MsgSystemClock', "", $Host::TimeLimit, %curTimeLeftMS); + + if( !$Host::TournamentMode && %cl.matchStartReady && %cl.camera.mode $= "pre-game") + { + commandToClient(%cl, 'setHudMode', 'Standard'); + %cl.setControlObject( %cl.player ); + } + else + { + if( %cl.matchStartReady ) + { + if(%cl.camera.mode $= "pre-game") + { + %cl.observerMode = ""; + commandToClient(%cl, 'setHudMode', 'Standard'); + + if(isObject(%cl.player)) + %cl.setControlObject( %cl.player ); + else + echo("can't set control for client: " @ %cl @ ", no player object found!"); + } + else + %cl.observerMode = "observerFly"; + } + } + } + + // on with the show this is it! + AISystemEnabled( true ); +} + +function DefaultGame::gameOver( %game ) +{ + //set the bool + $missionRunning = false; + + CancelCountdown(); + CancelEndCountdown(); + + //loop through all the clients, and do any cleanup... + %count = ClientGroup.getCount(); + for (%i = 0; %i < %count; %i++) + { + %client = ClientGroup.getObject(%i); + %player = %client.player; + %client.lastTeam = %client.team; + + if ( !%client.isAiControlled() ) + { + %client.endMission(); + messageClient( %client, 'MsgClearDebrief', "" ); + %game.sendDebriefing( %client ); + if(%client.player.isBomber) + commandToClient(%client, 'endBomberSight'); + + //clear the score hud... + messageClient( %client, 'SetScoreHudHeader', "", "" ); + messageClient( %client, 'SetScoreHudSubheader', "", ""); + messageClient( %client, 'ClearHud', "", 'scoreScreen', 0 ); + + // clean up the players' HUDs: + %client.setWeaponsHudClearAll(); + %client.setInventoryHudClearAll(); + } + } + + // Default game does nothing... except lets the AI know the mission is over + AIMissionEnd(); +} + +//------------------------------------------------------------------------------ +function DefaultGame::sendDebriefing( %game, %client ) +{ + if ( %game.numTeams == 1 ) + { + // Mission result: + %winner = $TeamRank[0, 0]; + if ( %winner.score > 0 ) + messageClient( %client, 'MsgDebriefResult', "", '%1 wins!', $TeamRank[0, 0].name ); + else + messageClient( %client, 'MsgDebriefResult', "", 'Nobody wins.' ); + + // Player scores: + %count = $TeamRank[0, count]; + messageClient( %client, 'MsgDebriefAddLine', "", 'PLAYERSCOREKILLS' ); + for ( %i = 0; %i < %count; %i++ ) + { + %cl = $TeamRank[0, %i]; + if ( %cl.score $= "" ) + %score = 0; + else + %score = %cl.score; + if ( %cl.kills $= "" ) + %kills = 0; + else + %kills = %cl.kills; + messageClient( %client, 'MsgDebriefAddLine', "", ' %1 %2 %3', %cl.name, %score, %kills ); + } + } + else + { + %topScore = ""; + %topCount = 0; + for ( %team = 1; %team <= %game.numTeams; %team++ ) + { + if ( %topScore $= "" || $TeamScore[%team] > %topScore ) + { + %topScore = $TeamScore[%team]; + %firstTeam = %team; + %topCount = 1; + } + else if ( $TeamScore[%team] == %topScore ) + { + %secondTeam = %team; + %topCount++; + } + } + + // Mission result: + if ( %topCount == 1 ) + messageClient( %client, 'MsgDebriefResult', "", 'Team %1 wins!', %game.getTeamName(%firstTeam) ); + else if ( %topCount == 2 ) + messageClient( %client, 'MsgDebriefResult', "", 'Team %1 and Team %2 tie!', %game.getTeamName(%firstTeam), %game.getTeamName(%secondTeam) ); + else + messageClient( %client, 'MsgDebriefResult', "", 'The mission ended in a tie.' ); + + // Team scores: + messageClient( %client, 'MsgDebriefAddLine', "", 'TEAMSCORE' ); + for ( %team = 1; %team - 1 < %game.numTeams; %team++ ) + { + if ( $TeamScore[%team] $= "" ) + %score = 0; + else + %score = $TeamScore[%team]; + messageClient( %client, 'MsgDebriefAddLine', "", ' %1 %2', %game.getTeamName(%team), %score ); + } + + // Player scores: + messageClient( %client, 'MsgDebriefAddLine', "", '\nPLAYERTEAMSCOREKILLS' ); + for ( %team = 1; %team - 1 < %game.numTeams; %team++ ) + %count[%team] = 0; + + %notDone = true; + while ( %notDone ) + { + // Get the highest remaining score: + %highScore = ""; + for ( %team = 1; %team <= %game.numTeams; %team++ ) + { + if ( %count[%team] < $TeamRank[%team, count] && ( %highScore $= "" || $TeamRank[%team, %count[%team]].score > %highScore ) ) + { + %highScore = $TeamRank[%team, %count[%team]].score; + %highTeam = %team; + } + } + + // Send the debrief line: + %cl = $TeamRank[%highTeam, %count[%highTeam]]; + %score = %cl.score $= "" ? 0 : %cl.score; + %kills = %cl.kills $= "" ? 0 : %cl.kills; + messageClient( %client, 'MsgDebriefAddLine', "", ' %1 %2 %3 %4', %cl.name, %game.getTeamName(%cl.team), %score, %kills ); + + %count[%highTeam]++; + %notDone = false; + for ( %team = 1; %team - 1 < %game.numTeams; %team++ ) + { + if ( %count[%team] < $TeamRank[%team, count] ) + { + %notDone = true; + break; + } + } + } + } + + //now go through an list all the observers: + %count = ClientGroup.getCount(); + %printedHeader = false; + for (%i = 0; %i < %count; %i++) + { + %cl = ClientGroup.getObject(%i); + if (%cl.team <= 0) + { + //print the header only if we actually find an observer + if (!%printedHeader) + { + %printedHeader = true; + messageClient(%client, 'MsgDebriefAddLine', "", '\nOBSERVERSSCORE'); + } + + //print out the client + %score = %cl.score $= "" ? 0 : %cl.score; + messageClient( %client, 'MsgDebriefAddLine', "", ' %1 %2', %cl.name, %score); + } + } +} + +//------------------------------------------------------------ +function DefaultGame::clearDeployableMaxes(%game) +{ + for(%i = 0; %i <= %game.numTeams; %i++) + { + $TeamDeployedCount[%i, TurretIndoorDeployable] = 0; + $TeamDeployedCount[%i, TurretOutdoorDeployable] = 0; + $TeamDeployedCount[%i, PulseSensorDeployable] = 0; + $TeamDeployedCount[%i, MotionSensorDeployable] = 0; + $TeamDeployedCount[%i, InventoryDeployable] = 0; + $TeamDeployedCount[%i, DeployedCamera] = 0; + $TeamDeployedCount[%i, MineDeployed] = 0; + $TeamDeployedCount[%i, TargetBeacon] = 0; + $TeamDeployedCount[%i, MarkerBeacon] = 0; + $TeamDeployedCount[%i, LargeInventoryDeployable] = 0; + $TeamDeployedCount[%i, GeneratorDeployable] = 0; + $TeamDeployedCount[%i, SolarPanelDeployable] = 0; + $TeamDeployedCount[%i, SwitchDeployable] = 0; + $TeamDeployedCount[%i, MediumSensorDeployable] = 0; + $TeamDeployedCount[%i, LargeSensorDeployable] = 0; + $TeamDeployedCount[%i, WallDeployable] = 0; + $TeamDeployedCount[%i, wWallDeployable] = 0; + $TeamDeployedCount[%i, SpineDeployable] = 0; + $TeamDeployedCount[%i, MSpineDeployable] = 0; + $TeamDeployedCount[%i, JumpadDeployable] = 0; + $TeamDeployedCount[%i, EscapePodDeployable] = 0; + $TeamDeployedCount[%i, EnergizerDeployable] = 0; + $TeamDeployedCount[%i, TreeDeployable] = 0; + $TeamDeployedCount[%i, CrateDeployable] = 0; + $TeamDeployedCount[%i, DecorationDeployable] = 0; + $TeamDeployedCount[%i, LogoProjectorDeployable] = 0; + $TeamDeployedCount[%i, LightDeployable] = 0; + $TeamDeployedCount[%i, TripwireDeployable] = 0; + $TeamDeployedCount[%i, ForceFieldDeployable] = 0; + $TeamDeployedCount[%i, GravityFieldDeployable] = 0; + $TeamDeployedCount[%i, TelePadPack] = 0; + $TeamDeployedCount[%i, TurretBasePack] = 0; + $TeamDeployedCount[%i, TurretLaserDeployable] = 0; + $TeamDeployedCount[%i, TurretMissileRackDeployable] = 0; + $TeamDeployedCount[%i, DiscTurretDeployable] = 0; + $TeamDeployedCount[%i, FloorDeployable] = 0; + + $TeamDeployedCount[%i, TurretMpm_Anti_Deployable] = 0; + $TeamDeployedCount[%i, VehiclePadPack] = 0; + $TeamDeployedCount[%i, EmitterDepPack] = 0; + + $TeamDeployedCount[%i, AudioDepPack] = 0; + $TeamDeployedCount[%i, DispenserDepPack] = 0; + $TeamDeployedCount[%i, MPM_BeaconPack] = 0; + $TeamDeployedCount[%i, DetonationDepPack] = 0; + $TeamDeployedCount[%i, MpmFuelPack] = 0; + $TeamDeployedCount[%i, MpmAmmoPack] = 0; + + } +} + +// called from player scripts +function DefaultGame::onClientDamaged(%game, %clVictim, %clAttacker, %damageType, %sourceObject) +{ + //set the vars if it was a turret + if (isObject(%sourceObject)) + { + %sourceClassType = %sourceObject.getDataBlock().getClassName(); + %sourceType = %sourceObject.getDataBlock().getName(); + } + if (%sourceClassType $= "TurretData") + { + // jff: are there special turret types which makes this needed? + // tinman: yes, we don't want bots stopping to fire on the big outdoor turrets, which they + // will just get mowed down. deployables only. + + if (isDeployedTurret(%sourceObject)) + { + %clVictim.lastDamageTurretTime = getSimTime(); + %clVictim.lastDamageTurret = %sourceObject; + } + + %turretAttacker = %sourceObject.getControllingClient(); + // should get a damagae message from friendly fire turrets also + if(%turretAttacker && %turretAttacker != %clVictim && %turretAttacker.team == %clVictim.team) + { + if (%game.numTeams > 1 && %turretAttacker.player.causedRecentDamage != %clVictim.player) //is a teamgame & player just damaged a teammate + { + %turretAttacker.player.causedRecentDamage = %clVictim.player; + %turretAttacker.player.schedule(1000, "causedRecentDamage", ""); //allow friendly fire message every x ms + %game.friendlyFireMessage(%clVictim, %turretAttacker); + } + } + } + else if (%sourceClassType $= "PlayerData") + { + //now see if both were on the same team + if(%clAttacker && %clAttacker != %clVictim && %clVictim.team == %clAttacker.team) + { + if (%game.numTeams > 1 && %clAttacker.player.causedRecentDamage != %clVictim.player) //is a teamgame & player just damaged a teammate + { + %clAttacker.player.causedRecentDamage = %clVictim.player; + %clAttacker.player.schedule(1000, "causedRecentDamage", ""); //allow friendly fire message every x ms + %game.friendlyFireMessage(%clVictim, %clAttacker); + } + } + if (%clAttacker && %clAttacker != %clVictim) + { + %clVictim.lastDamageTime = getSimTime(); + %clVictim.lastDamageClient = %clAttacker; + if (%clVictim.isAIControlled()) + %clVictim.clientDetected(%clAttacker); + } + } + + //call the game specific AI routines... + if (isObject(%clVictim) && %clVictim.isAIControlled()) + %game.onAIDamaged(%clVictim, %clAttacker, %damageType, %sourceObject); + if (isObject(%clAttacker) && %clAttacker.isAIControlled()) + %game.onAIFriendlyFire(%clVictim, %clAttacker, %damageType, %sourceObject); +} + +function DefaultGame::friendlyFireMessage(%game, %damaged, %damager) +{ + messageClient(%damaged, 'MsgDamagedByTeam', '\c1You were harmed by teammate %1', %damager.name); + messageClient(%damager, 'MsgDamagedTeam', '\c1You just harmed teammate %1.', %damaged.name); +} + +function DefaultGame::clearWaitRespawn(%game, %client) +{ + %client.waitRespawn = 0; +} + +// called from player scripts +function DefaultGame::onClientKilled(%game, %clVictim, %clKiller, %damageType, %implement, %damageLocation) +{ + if ($onClientKilledHook == 1) + onClientKilledHook(%clVictim); + + %plVictim = %clVictim.player; + %plKiller = %clKiller.player; + %clVictim.plyrPointOfDeath = %plVictim.position; + %clVictim.plyrDiedHoldingFlag = %plVictim.holdingFlag; + %clVictim.waitRespawn = 1; + + if ($Host::RepairPatchOnDeath == 1) { + %p = new Item () { + dataBlock = "RepairPatch"; + position = %plVictim.getWorldBoxCenter(); + static = true; + }; + %p.schedulePop(); + MissionCleanup.add(%p); + } + +//[[CHANGE]] Make sure the beacon get's removed.. as it should be.. :D + %clvictim.player.RemoveBeacon(); + + cancel( %plVictim.reCloak ); + cancel(%clVictim.respawnTimer); + %clVictim.respawnTimer = %game.schedule(($Host::PlayerRespawnTimeout * 1000), "forceObserver", %clVictim, "spawnTimeout" ); + + // reset the alarm for out of bounds + if(%clVictim.outOfBounds) + messageClient(%clVictim, 'EnterMissionArea', ""); + + %respawnDelay = 2; + + + %game.schedule(%respawnDelay*1000, "clearWaitRespawn", %clVictim); + // if victim had an undetonated satchel charge pack, get rid of it + if(%plVictim.thrownChargeId != 0) + if(!%plVictim.thrownChargeId.kaboom) + %plVictim.thrownChargeId.delete(); + + if(%plVictim.lastVehicle !$= "") + { + schedule(15000, %plVictim.lastVehicle,"vehicleAbandonTimeOut", %plVictim.lastVehicle); + %plVictim.lastVehicle.lastPilot = ""; + } + + // unmount pilot or remove sight from bomber + if(%plVictim.isMounted()) + { + if(%plVictim.vehicleTurret) + %plVictim.vehicleTurret.getDataBlock().playerDismount(%plVictim.vehicleTurret); + else + { + %plVictim.getDataBlock().doDismount(%plVictim, true); + %plVictim.mountVehicle = false; + } + } + + if(%plVictim.inStation) + commandToClient(%plVictim.client,'setStationKeys', false); + %clVictim.camera.mode = "playerDeath"; + + // reset who triggered this station and cancel outstanding armor switch thread + if(%plVictim.station) + { + %plVictim.station.triggeredBy = ""; + %plVictim.station.getDataBlock().stationTriggered(%plVictim.station,0); + if(%plVictim.armorSwitchSchedule) + cancel(%plVictim.armorSwitchSchedule); + } + + //Close huds if player dies... + messageClient(%clVictim, 'CloseHud', "", 'inventoryScreen'); + messageClient(%clVictim, 'CloseHud', "", 'vehicleHud'); + commandToClient(%clVictim, 'setHudMode', 'Standard', "", 0); + + // $weaponslot from item.cs + %plVictim.setRepairRate(0); + %plVictim.setImageTrigger($WeaponSlot, false); + + playDeathAnimation(%plVictim, %damageLocation, %damageType); + playDeathCry(%plVictim); + + %victimName = %clVictim.name; + + %game.displayDeathMessages(%clVictim, %clKiller, %damageType, %implement); + %game.updateKillScores(%clVictim, %clKiller, %damageType, %implement); + + if ($Host::Prison::Enabled == true && %clKiller != %clVictim + && ($Host::Prison::Kill == true || (%clKiller.team == %clVictim.team && $Host::Prison::TeamKill == true)) + && %clKiller.player // Make sure killer is a player + && !%clKiller.isAIControlled() && !%clVictim.isAIControlled() // Don't jail for bot actions + && !%clKiller.isAdmin && !%clKiller.isSuperAdmin) { // Don't jail admins/superadmins + %victimName = %clVictim.name; + if (%clKiller.team == %clVictim.team) // Avoid some repetitions + %victimName = "TEAMMATE " @ getTaggedString(%clVictim.name); + if ($Host::Prison::KillTime > 0) { + if ($Host::Prison::KillTime >= 60) { + if ($Host::Prison::KillTime > 60) { + %minutes = mFloor($Host::Prison::KillTime / 60); + messageClient(%clKiller,'msgClient','\c2You will do %2 minutes in jail for killing %1.',%victimName,%minutes); + messageAllExcept(%clKiller,-1,'msgClient','\c2%1 will do %3 minutes in jail for killing %2.',%clKiller.name,%victimName,%minutes); + } + else { + messageClient(%clKiller,'msgClient','\c2You will do 1 minute in jail for killing %1.',%victimName); + messageAllExcept(%clKiller,-1,'msgClient','\c2%1 will do 1 minute in jail for killing %2.',%clKiller.name,%victimName); + } + } + else { + messageClient(%clKiller,'msgClient','\c2You will do %2 seconds in jail for killing %1.',%victimName,$Host::Prison::KillTime); + messageAllExcept(%clKiller,-1,'msgClient','\c2%1 will do %3 seconds in jail for killing %2.',%clKiller.name,%victimName,$Host::Prison::KillTime); + } + } + else { + messageClient(%clKiller,'msgClient','\c2You were put in jail for killing %1.',%victimName); + messageAllExcept(%clKiller,-1,'msgClient','\c2%1 was put in jail for killing %2.',%clKiller.name,%victimName); + } + jailPlayer(%clKiller,false,$Host::Prison::KillTime); + } + + // toss whatever is being carried, '$flagslot' from item.cs + // MES - had to move this to after death message display because of Rabbit game type + for(%index = 0 ; %index < 8; %index++) + { + %image = %plVictim.getMountedImage(%index); + if(%image) + { + if(%index == $FlagSlot) + %plVictim.throwObject(%plVictim.holdingFlag); + else + %plVictim.throw(%image.item); + } + } + + // target manager update + setTargetDataBlock(%clVictim.target, 0); + setTargetSensorData(%clVictim.target, 0); + + // clear the hud + %clVictim.SetWeaponsHudClearAll(); + %clVictim.SetInventoryHudClearAll(); + %clVictim.setAmmoHudCount(-1); + + // clear out weapons, inventory and pack huds + messageClient(%clVictim, 'msgDeploySensorOff', ""); //make sure the deploy hud gets shut off + messageClient(%clVictim, 'msgPackIconOff', ""); // clear the pack icon + + //clear the deployable HUD + %plVictim.client.deployPack = false; + cancel(%plVictim.deployCheckThread); + deactivateDeploySensor(%plVictim); + + //if the killer was an AI... + if (isObject(%clKiller) && %clKiller.isAIControlled()) + %game.onAIKilledClient(%clVictim, %clKiller, %damageType, %implement); + + + // reset control object on this player: also sets 'playgui' as content + serverCmdResetControlObject(%clVictim); + + // set control object to the camera + %clVictim.player = 0; + %transform = %plVictim.getTransform(); + + //note, AI's don't have a camera... + if (isObject(%clVictim.camera)) + { + %clVictim.camera.setTransform(%transform); + %clVictim.camera.setOrbitMode(%plVictim, %plVictim.getTransform(), 0.5, 4.5, 4.5); + %clVictim.setControlObject(%clVictim.camera); + } + + //hook in the AI specific code for when a client dies + if (%clVictim.isAIControlled()) + { + aiReleaseHumanControl(%clVictim.controlByHuman, %clVictim); + %game.onAIKilled(%clVictim, %clKiller, %damageType, %implement); + } + else + aiReleaseHumanControl(%clVictim, %clVictim.controlAI); + + //used to track corpses so the AI can get ammo, etc... + AICorpseAdded(%plVictim); + + //if the death was a suicide, prevent respawning for 5 seconds... + %clVictim.lastDeathSuicide = false; + if (%damageType == $DamageType::Suicide) + { +// %clVictim.lastDeathSuicide = true; +// %clVictim.suicideRespawnTime = getSimTime() + 5000; + } +} + +function DefaultGame::forceObserver( %game, %client, %reason ) +{ + //make sure we have a valid client... + if (%client <= 0) + return; + + // first kill this player + if(%client.player) + %client.player.scriptKill(0); + + if( %client.respawnTimer ) + cancel(%client.respawnTimer); + + %client.respawnTimer = ""; + + // remove them from the team rank array + %game.removeFromTeamRankArray(%client); + + // place them in observer mode + %client.lastObserverSpawn = -1; + %client.observerStartTime = getSimTime(); + %adminForce = 0; + + switch$ ( %reason ) + { + case "playerChoose": + %client.camera.getDataBlock().setMode( %client.camera, "observerFly" ); + messageClient(%client, 'MsgClientJoinTeam', '\c2You have become an observer.', %client.name, %game.getTeamName(0), %client, 0 ); + logEcho(%client.nameBase@" (cl "@%client@") entered observer mode"); + %client.lastTeam = %client.team; + + case "AdminForce": + %client.camera.getDataBlock().setMode( %client.camera, "observerFly" ); + messageClient(%client, 'MsgClientJoinTeam', '\c2You have been forced into observer mode by the admin.', %client.name, %game.getTeamName(0), %client, 0 ); + logEcho(%client.nameBase@" (cl "@%client@") was forced into observer mode by admin"); + %client.lastTeam = %client.team; + %adminForce = 1; + + if($Host::TournamentMode) + { + if(!$matchStarted) + { + if(%client.camera.Mode $= "pickingTeam") + { + commandToClient( %client, 'processPickTeam'); + clearBottomPrint( %client ); + } + else + { + clearCenterPrint(%client); + %client.notReady = true; + } + } + } + + case "spawnTimeout": + %client.camera.getDataBlock().setMode( %client.camera, "observerTimeout" ); + messageClient(%client, 'MsgClientJoinTeam', '\c2You have been placed in observer mode due to delay in respawning.', %client.name, %game.getTeamName(0), %client, 0 ); + logEcho(%client.nameBase@" (cl "@%client@") was placed in observer mode due to spawn delay"); + // save the team the player was on - only if this was a delay in respawning + %client.lastTeam = %client.team; + } + + // switch client to team 0 (observer) + %client.team = 0; + %client.player.team = 0; + setTargetSensorGroup( %client.target, %client.team ); + %client.setSensorGroup( %client.team ); + + // set their control to the obs. cam + %client.setControlObject( %client.camera ); + commandToClient(%client, 'setHudMode', 'Observer'); + + // display the hud + //displayObserverHud(%client, 0); + updateObserverFlyHud(%client); + + + // message everyone about this event + if( !%adminForce ) + messageAllExcept(%client, -1, 'MsgClientJoinTeam', '\c2%1 has become an observer.', %client.name, %game.getTeamName(0), %client, 0 ); + else + messageAllExcept(%client, -1, 'MsgClientJoinTeam', '\c2The admin has forced %1 to become an observer.', %client.name, %game.getTeamName(0), %client, 0 ); + + updateCanListenState( %client ); + + // call the onEvent for this game type + %game.onClientEnterObserverMode(%client); //Bounty uses this to remove this client from others' hit lists +} + +function DefaultGame::displayDeathMessages(%game, %clVictim, %clKiller, %damageType, %implement) +{ + // ---------------------------------------------------------------------------------- + // z0dd - ZOD, 6/18/02. From Panama Jack, send the damageTypeText as the last varible + // in each death message so client knows what weapon it was that killed them. + + %victimGender = (%clVictim.sex $= "Male" ? 'him' : 'her'); + %victimPoss = (%clVictim.sex $= "Male" ? 'his' : 'her'); + %killerGender = (%clKiller.sex $= "Male" ? 'him' : 'her'); + %killerPoss = (%clKiller.sex $= "Male" ? 'his' : 'her'); + %victimName = %clVictim.name; + %killerName = %clKiller.name; + //error("DamageType = " @ %damageType @ ", implement = " @ %implement @ ", implement class = " @ %implement.getClassName() @ ", is controlled = " @ %implement.getControllingClient()); + + if(%damageType == $DamageType::Explosion) + { + messageAll('msgExplosionKill', $DeathMessageExplosion[mFloor(getRandom() * $DeathMessageExplosionCount)], %victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType, $DamageTypeText[%damageType]); + logEcho(%clVictim.nameBase@" (pl "@%clVictim.player@"/cl "@%clVictim@") killed by a nearby explosion."); + } + else if(%damageType == $DamageType::Suicide) //player presses cntrl-k + { + messageAll('msgSuicide', $DeathMessageSuicide[mFloor(getRandom() * $DeathMessageSuicideCount)], %victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType, $DamageTypeText[%damageType]); + logEcho(%clVictim.nameBase@" (pl "@%clVictim.player@"/cl "@%clVictim@") committed suicide (CTRL-K)"); + } + else if(%damageType == $DamageType::VehicleSpawn) + { + messageAll('msgVehicleSpawnKill', $DeathMessageVehPad[mFloor(getRandom() * $DeathMessageVehPadCount)], %victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType, $DamageTypeText[%damageType]); + logEcho(%clVictim.nameBase@" (pl "@%clVictim.player@"/cl "@%clVictim@") killed by vehicle spawn"); + } + else if(%damageType == $DamageType::ForceFieldPowerup) + { + messageAll('msgVehicleSpawnKill', $DeathMessageFFPowerup[mFloor(getRandom() * $DeathMessageFFPowerupCount)], %victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType, $DamageTypeText[%damageType]); + logEcho(%clVictim.nameBase@" (pl "@%clVictim.player@"/cl "@%clVictim@") killed by Force Field Powerup"); + } + else if(%damageType == $DamageType::Crash) + { + messageAll('msgVehicleCrash', $DeathMessageVehicleCrash[%damageType, mFloor(getRandom() * $DeathMessageVehicleCrashCount)], %victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType, $DamageTypeText[%damageType]); + logEcho(%clVictim.nameBase@" (pl "@%clVictim.player@"/cl "@%clVictim@") crashes a vehicle."); + } + else if(%damageType == $DamageType::Impact) // run down by vehicle + { + if( ( %controller = %implement.getControllingClient() ) > 0) + { + %killerGender = (%controller.sex $= "Male" ? 'him' : 'her'); + %killerPoss = (%controller.sex $= "Male" ? 'his' : 'her'); + %killerName = %controller.name; + messageAll('msgVehicleKill', $DeathMessageVehicle[mFloor(getRandom() * $DeathMessageVehicleCount)], %victimName, %victimGender, %victimPoss, %killerName ,%killerGender, %killerPoss, %damageType, $DamageTypeText[%damageType]); + logEcho(%clVictim.nameBase@" (pl "@%clVictim.player@"/cl "@%clVictim@") killed by a vehicle controlled by "@%controller); + } + else + { + messageAll('msgVehicleKill', $DeathMessageVehicleUnmanned[mFloor(getRandom() * $DeathMessageVehicleUnmannedCount)], %victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType, $DamageTypeText[%damageType]); + logEcho(%clVictim.nameBase@" (pl "@%clVictim.player@"/cl "@%clVictim@") killed by a vehicle (unmanned)"); + } + } + else if (isObject(%implement) && (%implement.getClassName() $= "Turret" || %implement.getClassName() $= "VehicleTurret" || %implement.getClassName() $= "FlyingVehicle" )) //player killed by a turret + { + if (%implement.getControllingClient() != 0) //is turret being controlled? + { + %controller = %implement.getControllingClient(); + %killerGender = (%controller.sex $= "Male" ? 'him' : 'her'); + %killerPoss = (%controller.sex $= "Male" ? 'his' : 'her'); + %killerName = %controller.name; + + if (%controller == %clVictim) + messageAll('msgTurretSelfKill', $DeathMessageTurretSelfKill[mFloor(getRandom() * $DeathMessageTurretSelfKillCount)],%victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType, $DamageTypeText[%damageType]); + else if (%controller.team == %clVictim.team) //controller TK'd a friendly + messageAll('msgCTurretKill', $DeathMessageCTurretTeamKill[%damageType, mFloor(getRandom() * $DeathMessageCTurretTeamKillCount)],%victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType, $DamageTypeText[%damageType]); + else //controller killed an enemy + messageAll('msgCTurretKill', $DeathMessageCTurretKill[%damageType, mFloor(getRandom() * $DeathMessageCTurretKillCount)],%victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType, $DamageTypeText[%damageType]); + logEcho(%clVictim.nameBase@" (pl "@%clVictim.player@"/cl "@%clVictim@") killed by a turret controlled by "@%controller); + } + // use the handle associated with the deployed object to verify valid owner + else if (isObject(%implement.getOwner())) + { + %owner = %implement.getOwner(); + //error("Owner is " @ %owner @ " Handle is " @ %implement.ownerHandle); + //error("Turret is still owned"); + //turret is uncontrolled, but is owned - treat the same as controlled. + %killerGender = (%owner.sex $= "Male" ? 'him' : 'her'); + %killerPoss = (%owner.sex $= "Male" ? 'his' : 'her'); + %killerName = %owner.name; + + if (%owner.team == %clVictim.team) //player got in the way of a teammates deployed but uncontrolled turret. + messageAll('msgCTurretKill', $DeathMessageCTurretAccdtlKill[%damageType,mFloor(getRandom() * $DeathMessageCTurretAccdtlKillCount)],%victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType, $DamageTypeText[%damageType]); + else //deployed, uncontrolled turret killed an enemy + messageAll('msgCTurretKill', $DeathMessageCTurretKill[%damageType,mFloor(getRandom() * $DeathMessageCTurretKillCount)],%victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType, $DamageTypeText[%damageType]); + logEcho(%clVictim.nameBase@" (pl "@%clVictim.player@"/cl "@%clVictim@") was killed by turret (automated)"); + } + else //turret is not a placed (owned) turret (or owner is no longer on it's team), and is not being controlled + { + messageAll('msgTurretKill', $DeathMessageTurretKill[%damageType,mFloor(getRandom() * $DeathMessageTurretKillCount)],%victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType, $DamageTypeText[%damageType]); + logEcho(%clVictim.nameBase@" (pl "@%clVictim.player@"/cl "@%clVictim@") killed by turret"); + } + } + else if((%clKiller == %clVictim) || (%damageType == $DamageType::Ground)) //player killed himself or fell to death + { + messageAll('msgSelfKill', $DeathMessageSelfKill[%damageType,mFloor(getRandom() * $DeathMessageSelfKillCount)], %victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType, $DamageTypeText[%damageType]); + logEcho(%clVictim.nameBase@" (pl "@%clVictim.player@"/cl "@%clVictim@") killed self ("@getTaggedString($DamageTypeText[%damageType])@")"); + } + + else if (%damageType == $DamageType::OutOfBounds) //killer died due to Out-of-Bounds damage + { + messageAll('msgOOBKill', $DeathMessageOOB[mFloor(getRandom() * $DeathMessageOOBCount)], %victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType, $DamageTypeText[%damageType]); + logEcho(%clVictim.nameBase@" (pl "@%clVictim.player@"/cl "@%clVictim@") killed by out-of-bounds damage"); + } + + else if (%damageType == $DamageType::NexusCamping) //Victim died from camping near the nexus... + { + messageAll('msgCampKill', $DeathMessageCamping[mFloor(getRandom() * $DeathMessageCampingCount)], %victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType, $DamageTypeText[%damageType]); + logEcho(%clVictim.nameBase@" (pl "@%clVictim.player@"/cl "@%clVictim@") killed for nexus camping"); + } + + else if(%clKiller.team == %clVictim.team) //was a TK + { + messageAll('msgTeamKill', $DeathMessageTeamKill[%damageType, mFloor(getRandom() * $DeathMessageTeamKillCount)], %victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType, $DamageTypeText[%damageType]); + logEcho(%clVictim.nameBase@" (pl "@%clVictim.player@"/cl "@%clVictim@") teamkilled by "@%clKiller.nameBase@" (pl "@%clKiller.player@"/cl "@%clKiller@")"); + } + + else if (%damageType == $DamageType::Lava) //player died by falling in lava + { + messageAll('msgLavaKill', $DeathMessageLava[mFloor(getRandom() * $DeathMessageLavaCount)], %victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType, $DamageTypeText[%damageType]); + logEcho(%clVictim.nameBase@" (pl "@%clVictim.player@"/cl "@%clVictim@") killed by lava"); + } + else if ( %damageType == $DamageType::Lightning ) // player was struck by lightning + { + messageAll('msgLightningKill', $DeathMessageLightning[mFloor(getRandom() * $DeathMessageLightningCount)], %victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType, $DamageTypeText[%damageType]); + logEcho(%clVictim.nameBase@" (pl "@%clVictim.player@"/cl "@%clVictim@") killed by lightning"); + } + else if ( %damageType == $DamageType::Meteor ) // player was struck by meteor + { + messageAll('msgMeteorKill', $DeathMessageMeteor[mFloor(getRandom() * $DeathMessageMeteorCount)], %victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType, $DamageTypeText[%damageType]); + logEcho(%clVictim.nameBase@" (pl "@%clVictim.player@"/cl "@%clVictim@") killed by meteor"); + } + else if ( %damageType == $DamageType::Cursing ) // player cursing + { + messageAll('msgCursingKill', $DeathMessageCursing[mFloor(getRandom() * $DeathMessageCursingCount)], %victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType, $DamageTypeText[%damageType]); + logEcho(%clVictim.nameBase@" (pl "@%clVictim.player@"/cl "@%clVictim@") killed by cursing"); + } + else if ( %damageType == $DamageType::Idiocy ) // player was dumb + { + messageAll('msgIdiocyKill', $DeathMessageIdiocy[mFloor(getRandom() * $DeathMessageIdiocyCount)], %victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType, $DamageTypeText[%damageType]); + logEcho(%clVictim.nameBase@" (pl "@%clVictim.player@"/cl "@%clVictim@") killed by idiocy"); + } + else if ( %damageType == $DamageType::KillerFog ) // player fell into killer fog + { + messageAll('msgKillerFogKill', $DeathMessageKillerFog[mFloor(getRandom() * $DeathMessageKillerFogCount)], %victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType, $DamageTypeText[%damageType]); + logEcho(%clVictim.nameBase@" (pl "@%clVictim.player@"/cl "@%clVictim@") killed by killer fog"); + } + else if ( %damageType == $DamageType::Mine && !isObject(%clKiller) ) + { + error("Mine kill w/o source"); + messageAll('MsgRogueMineKill', $DeathMessageRogueMine[%damageType, mFloor(getRandom() * $DeathMessageRogueMineCount)], %victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType, $DamageTypeText[%damageType]); + } + else //was a legitimate enemy kill + { + if(%damageType == 6 && (%clVictim.headShot)) + { + // laser headshot just occurred + messageAll('MsgHeadshotKill', $DeathMessageHeadshot[%damageType, mFloor(getRandom() * $DeathMessageHeadshotCount)], %victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType, $DamageTypeText[%damageType]); + + } + else + messageAll('MsgLegitKill', $DeathMessage[%damageType, mFloor(getRandom() * $DeathMessageCount)], %victimName, %victimGender, %victimPoss, %killerName, %killerGender, %killerPoss, %damageType, $DamageTypeText[%damageType]); + logEcho(%clVictim.nameBase@" (pl "@%clVictim.player@"/cl "@%clVictim@") killed by "@%clKiller.nameBase@" (pl "@%clKiller.player@"/cl "@%clKiller@") using "@getTaggedString($DamageTypeText[%damageType])); + } +} + +function DefaultGame::assignClientTeam(%game, %client, %respawn ) +{ +//error("DefaultGame::assignClientTeam"); + // this function is overwritten in non-team mission types (e.g. DM) + // so these lines won't do anything + //if(!%game.numTeams) + //{ + // setTargetSkin(%client.target, %client.skin); + // return; + //} + + // camera is responsible for creating a player + // - counts the number of players per team + // - puts this player on the least player count team + // - sets the client's skin to the servers default + + %numPlayers = ClientGroup.getCount(); + for(%i = 0; %i <= %game.numTeams; %i++) + %numTeamPlayers[%i] = 0; + + for(%i = 0; %i < %numPlayers; %i = %i + 1) + { + %cl = ClientGroup.getObject(%i); + if(%cl != %client) + %numTeamPlayers[%cl.team]++; + } + %leastPlayers = %numTeamPlayers[1]; + %leastTeam = 1; + for(%i = 2; %i <= %game.numTeams; %i++) + { + if( (%numTeamPlayers[%i] < %leastPlayers) || + ( (%numTeamPlayers[%i] == %leastPlayers) && + ($teamScore[%i] < $teamScore[%leastTeam] ) )) + { + %leastTeam = %i; + %leastPlayers = %numTeamPlayers[%i]; + } + } + + %client.team = %leastTeam; + %client.lastTeam = %team; + + // Assign the team skin: + if ( %client.isAIControlled() ) + { + if ( %leastTeam & 1 ) + { + %client.skin = addTaggedString( "basebot" ); + setTargetSkin( %client.target, 'basebot' ); + } + else + { + %client.skin = addTaggedString( "basebbot" ); + setTargetSkin( %client.target, 'basebbot' ); + } + } + else + setTargetSkin( %client.target, %game.getTeamSkin(%client.team) ); + //setTargetSkin( %client.target, %client.skin ); + + // might as well standardize the messages + //messageAllExcept( %client, -1, 'MsgClientJoinTeam', '\c1%1 joined %2.', %client.name, $teamName[%leastTeam], %client, %leastTeam ); + //messageClient( %client, 'MsgClientJoinTeam', '\c1You joined the %2 team.', $client.name, $teamName[%client.team], %client, %client.team ); + messageAllExcept( %client, -1, 'MsgClientJoinTeam', '\c1%1 joined %2.', %client.name, %game.getTeamName(%client.team), %client, %client.team ); + messageClient( %client, 'MsgClientJoinTeam', '\c1You joined the %2 team.', %client.name, %game.getTeamName(%client.team), %client, %client.team ); + + updateCanListenState( %client ); + + logEcho(%client.nameBase@" (cl "@%client@") joined team "@%client.team); +} + +function DefaultGame::getTeamSkin(%game, %team) +{ + //error("DefaultGame::getTeamSkin"); + %skin = $teamSkin[%team]; + //error("%skin = " SPC getTaggedString(%skin)); + return %skin; +} + +function DefaultGame::getTeamName(%game, %team) +{ + //error("DefaultGame::getTeamName"); + %name = $teamName[%team]; + //error("name = " SPC getTaggedString(%name)); + return %name; +} + +function DefaultGame::clientJoinTeam( %game, %client, %team, %respawn ) +{ + // for multi-team games played with a single team + if (Game.numTeams == 1) { + %game.assignClientTeam( %client ); + // Spawn the player: + %game.spawnPlayer( %client, %respawn ); + return; + } + +//error("DefaultGame::clientJoinTeam"); + if ( %team < 1 || %team > %game.numTeams ) + return; + + if( %respawn $= "" ) + %respawn = 1; + + %client.team = %team; + %client.lastTeam = %team; + setTargetSkin( %client.target, %game.getTeamSkin(%team) ); + setTargetSensorGroup( %client.target, %team ); + %client.setSensorGroup( %team ); + + // Spawn the player: + %game.spawnPlayer( %client, %respawn ); + + messageAllExcept( %client, -1, 'MsgClientJoinTeam', '\c1%1 joined %2.', %client.name, %game.getTeamName(%team), %client, %team ); + messageClient( %client, 'MsgClientJoinTeam', '\c1You joined the %2 team.', $client.name, %game.getTeamName(%client.team), %client, %client.team ); + + updateCanListenState( %client ); + + logEcho(%client.nameBase@" (cl "@%client@") joined team "@%client.team); + if ($Host::Prison::Enabled == true) { + if (%client.isJailed) + // If player should manage to get out of jail, re-spawn and re-start sentence time + jailPlayer(%client,false,mAbs(%cl.jailTime)); + } +} + +function DefaultGame::AIHasJoined(%game, %client) +{ + //defined to prevent console spam +} + +function DefaultGame::AIChangeTeam(%game, %client, %newTeam) +{ + //make sure we're trying to drop an AI + if (!isObject(%client) || !%client.isAIControlled()) + return; + + //clear the ai from any objectives, etc... + AIUnassignClient(%client); + %client.stop(); + %client.clearTasks(); + %client.clearStep(); + %client.lastDamageClient = -1; + %client.lastDamageTurret = -1; + %client.shouldEngage = -1; + %client.setEngageTarget(-1); + %client.setTargetObject(-1); + %client.pilotVehicle = false; + %client.defaultTasksAdded = false; + + //kill the player, which should cause the Game object to perform whatever cleanup is required. + if (isObject(%client.player)) + %client.player.scriptKill(0); + + //clean up the team rank array + %game.removeFromTeamRankArray(%client); + + //assign the new team + %client.team = %newTeam; + if (%newTeam < 0) + Game.assignClientTeam(%client); + else + { + if ( %client.team & 1 ) + { + %client.skin = addTaggedString( "basebot" ); + setTargetSkin( %client.target, 'basebot' ); + } + else + { + %client.skin = addTaggedString( "basebbot" ); + setTargetSkin( %client.target, 'basebbot' ); + } + } + + messageAllExcept( %client, -1, 'MsgClientJoinTeam', '\c1bot %1 has switched to team %2.', %client.name, %game.getTeamName(%client.team), %client, %client.team ); +} + +function DefaultGame::clientChangeTeam(%game, %client, %team, %fromObs) +{ +//error("DefaultGame::clientChangeTeam"); + //first, remove the client from the team rank array + //the player will be added to the new team array as soon as he respawns... + %game.removeFromTeamRankArray(%client); + + %pl = %client.player; + if(isObject(%pl)) + { + if(%pl.isMounted()) + %pl.getDataBlock().doDismount(%pl); + %pl.scriptKill(0); + } + + // reset the client's targets and tasks only + clientResetTargets(%client, true); + + // give this client a new handle to disassociate ownership of deployed objects + if( %team $= "" && (%team > 0 && %team <= %game.numTeams)) + { + if( %client.team == 1 ) + %client.team = 2; + else + %client.team = 1; + } + else + %client.team = %team; + +// Shouldn't be needed - serverCmds are proofed (hopefully) +// As it is, it just prevents admins from changing non-admins to a non-valid team +// if (!(%client.isAdmin || %client.isSuperAdmin)) { +// if (%team > %game.numTeams || %team $= "") +// %team = 1; +// } + + // Set the client's skin: + if (!%client.isAIControlled()) + setTargetSkin( %client.target, %game.getTeamSkin(%client.team) ); + setTargetSensorGroup( %client.target, %client.team ); + %client.setSensorGroup( %client.team ); + + // Spawn the player: + %client.lastSpawnPoint = %game.pickPlayerSpawn( %client ); + + %game.createPlayer( %client, %client.lastSpawnPoint, $MatchStarted ); + + if($MatchStarted) + %client.setControlObject(%client.player); + else + { + %client.camera.getDataBlock().setMode(%client.camera, "pre-game", %client.player); + %client.setControlObject(%client.camera); + } + + // call the onEvent for this game type + %game.onClientEnterObserverMode(%client); //Bounty uses this to remove this client from others' hit lists + + if(%fromObs $= "" || !%fromObs) + { + messageAllExcept( %client, -1, 'MsgClientJoinTeam', '\c1%1 switched to team %2.', %client.name, %game.getTeamName(%client.team), %client, %client.team ); + messageClient( %client, 'MsgClientJoinTeam', '\c1You switched to team %2.', $client.name, %game.getTeamName(%client.team), %client, %client.team ); + } + else + { + messageAllExcept( %client, -1, 'MsgClientJoinTeam', '\c1%1 joined team %2.', %client.name, %game.getTeamName(%client.team), %client, %team ); + messageClient( %client, 'MsgClientJoinTeam', '\c1You joined team %2.', $client.name, %game.getTeamName(%client.team), %client, %client.team ); + } + + updateCanListenState( %client ); + + // MES - switch objective hud lines when client switches teams + messageClient(%client, 'MsgCheckTeamLines', "", %client.team); + logEcho(%client.nameBase@" (cl "@%client@") switched to team "@%client.team); +} + +// missioncleanup and missiongroup are checked prior to entering game code +function DefaultGame::missionLoadDone(%game) +{ + // walks through the mission group and sets the power stuff up + // - groups get initialized with power count 0 then iterated to + // increment powercount if an object within is powered + // - powers objects up/down + //MissionGroup.objectiveInit(); + MissionGroup.clearPower(); + MissionGroup.powerInit(0); + + %game.initGameVars(); //set up scoring variables and other game specific globals + + // make team0 visible/friendly to all + setSensorGroupAlwaysVisMask(0, 0xffffffff); + setSensorGroupFriendlyMask(0, 0xffffffff); + + // update colors: + // - enemy teams are red + // - same team is green + // - team 0 is white + for(%i = 0; %i < 32; %i++) + { + %team = (1 << %i); + setSensorGroupColor(%i, %team, "0 255 0 255"); + setSensorGroupColor(%i, ~%team, "255 0 0 255"); + setSensorGroupColor(%i, 1, "255 255 255 255"); + + // setup the team targets (alwyas friendly and visible to same team) + setTargetAlwaysVisMask(%i, %team); + setTargetFriendlyMask(%i, %team); + } + + //set up the teams + %game.setUpTeams(); + + //clear out the team rank array... + for (%i = 0; %i < 32; %i++) + $TeamRank[%i, count] = ""; + + // objectiveInit has to take place after setupTeams -- objective HUD relies on flags + // having their team set + MissionGroup.objectiveInit(); + + //initialize the AI system + %game.aiInit(); + + //need to reset the teams if we switch from say, CTF to Bounty... + // assign the bots team + if ($currentMissionType !$= $previousMissionType) + { + $previousMissionType = $currentMissionType; + for(%i = 0; %i < ClientGroup.getCount(); %i++) + { + %cl = ClientGroup.getObject(%i); + if (%cl.isAIControlled()) + %game.assignClientTeam(%cl); + } + } + + //Save off respawn or Siege Team switch information... + if(%game.class !$= "SiegeGame") + MissionGroup.setupPositionMarkers(true); + echo("Default game mission load done."); +} + +function DefaultGame::onClientLeaveGame(%game, %client) +{ + // if there is a player attached to this client, kill it + if( isObject(%client.player)) + %client.player.scriptKill(0); + + //cancel a scheduled call... + cancel(%client.respawnTimer); + %client.respawnTimer = ""; + + //remove them from the team rank arrays + %game.removeFromTeamRankArray(%client); + logEcho(%client.nameBase@" (cl "@%client@") dropped"); +} + +function DefaultGame::clientMissionDropReady(%game, %client) +{ + //synchronize the clock HUD + messageClient(%client, 'MsgSystemClock', "", 0, 0); + + %game.sendClientTeamList( %client ); + %game.setupClientHuds( %client ); + + if($CurrentMissionType $= "SinglePlayer") + { + //CommandToClient( %client, 'setPlayContent'); + return; + } + + %observer = false; + if( !$Host::TournamentMode ) + { + if( %client.camera.mode $= "observerFly" || %client.camera.mode $= "justJoined") + { + %observer = true; + %client.observerStartTime = getSimTime(); + commandToClient(%client, 'setHudMode', 'Observer'); + %client.setControlObject( %client.camera ); + //displayObserverHud( %client, 0 ); + updateObserverFlyHud(%client); + } + + if( !%observer ) + { + if(!$MatchStarted && !$CountdownStarted) // server has not started anything yet + { + %client.setControlObject( %client.camera ); + commandToClient(%client, 'setHudMode', 'Observer'); + } + else if(!$MatchStarted && $CountdownStarted) // server has started the countdown + { + commandToClient(%client, 'setHudMode', 'Observer'); + %client.setControlObject( %client.camera ); + } + else + { + commandToClient(%client, 'setHudMode', 'Standard'); // the game has already started + %client.setControlObject( %client.player ); + } + } + } + else + { + // set all players into obs mode. setting the control object will handle further procedures... + %client.camera.getDataBlock().setMode( %client.camera, "ObserverFly" ); + commandToClient(%client, 'setHudMode', 'Observer'); + %client.setControlObject( %client.camera ); + messageAll( 'MsgClientJoinTeam', "",%client.name, $teamName[0], %client, 0 ); + %client.team = 0; + + if( !$MatchStarted && !$CountdownStarted) + { + if($TeamDamage) + %damMess = "ENABLED"; + else + %damMess = "DISABLED"; + + if(%game.numTeams > 1) + BottomPrint(%client, "Server is Running in Tournament Mode.\nPick a Team\nTeam Damage is " @ %damMess, 0, 3 ); + } + else + { + BottomPrint( %client, "\nServer is Running in Tournament Mode", 0, 3 ); + } + } + + //make sure the objective HUD indicates your team on top and in green... + if (%client.team > 0) + messageClient(%client, 'MsgCheckTeamLines', "", %client.team); + + // were ready to go. + %client.matchStartReady = true; + echo("Client" SPC %client SPC "is ready."); + + if ( isDemo() ) + { + if ( %client.demoJustJoined ) + { + %client.demoJustJoined = false; + centerPrint( %client, "Welcome to the Tribes 2 Demo." NL "You have been assigned the name \"" @ %client.nameBase @ "\"." NL "Press FIRE to join the game.", 0, 3 ); + } + } +} + +function DefaultGame::sendClientTeamList(%game, %client) +{ + // Send the client the current team list: + %teamCount = %game.numTeams; + for ( %i = 0; %i < %teamCount; %i++ ) + { + if ( %i > 0 ) + %teamList = %teamList @ "\n"; + + %teamList = %teamList @ detag( getTaggedString( %game.getTeamName(%i + 1) ) ); + } + messageClient( %client, 'MsgTeamList', "", %teamCount, %teamList ); +} + +function DefaultGame::setupClientHuds(%game, %client) +{ + // tell the client to setup the huds... + for(%i =0; %i<$WeaponsHudCount; %i++) + %client.setWeaponsHudBitmap(%i, $WeaponsHudData[%i, itemDataName], $WeaponsHudData[%i, bitmapName]); + for(%i =0; %i<$InventoryHudCount; %i++) + { + if ( $InventoryHudData[%i, slot] != 0 ) + %client.setInventoryHudBitmap($InventoryHudData[%i, slot], $InventoryHudData[%i, itemDataName], $InventoryHudData[%i, bitmapName]); + } + %client.setInventoryHudBitmap( 0, "", "gui/hud_handgren" ); + + %client.setWeaponsHudBackGroundBmp("gui/hud_new_panel"); + %client.setWeaponsHudHighLightBmp("gui/hud_new_weaponselect"); + %client.setWeaponsHudInfiniteAmmoBmp("gui/hud_infinity"); + %client.setInventoryHudBackGroundBmp("gui/hud_new_panel"); + + // tell the client if we are protecting statics (so no health bar will be displayed) +// We have deployable station inventories that can be destroyed, and thus we need the health bars +// commandToClient(%client, 'protectingStaticObjects', %game.allowsProtectedStatics()); + commandToClient(%client, 'setPowerAudioProfiles', sPowerUp.getId(), sPowerDown.getId()); +} + +function DefaultGame::testDrop( %game, %client ) +{ + %game.clientJoinTeam( %client, 1, false ); + %client.camera.getDataBlock().setMode( %client.camera, "pre-game", %client.player ); + %client.setControlObject( %client.camera ); + CommandToClient( %client, 'setPlayContent' ); +} + +function DefaultGame::onClientEnterObserverMode( %game, %client ) +{ + // Default game doesn't care... +} + +// from 'item.cs' +function DefaultGame::playerTouchFlag(%game, %player, %flag) +{ + messageAll('MsgPlayerTouchFlag', 'Player %1 touched flag %2', %player, %flag); +} + +// from 'item.cs' +function DefaultGame::playerDroppedFlag(%game, %player, %flag) +{ + messageAll('MsgPlayerDroppedFlag', 'Player %1 dropped flag %2', %player, %flag); +} + +// from 'staticShape.cs' +function DefaultGame::flagStandCollision(%game, %dataBlock, %obj, %colObj) +{ + // for retreiveGame +} + +function DefaultGame::notifyMineDeployed(%game, %mine) +{ + //do nothign in the default game... +} + +// from 'staticshape.cs' +function DefaultGame::findProjector(%game, %flipflop) +{ + // search the flipflop's folder for a holo projector + // if one exists, associate it with the flipflop + %flipflop.projector = 0; + %folder = %flipflop.getGroup(); + for(%i = 0; %i < %folder.getCount(); %i++) + { + %proj = %folder.getObject(%i); + if(%proj.getDatablock().getName() $= "LogoProjector") + { + %flipflop.projector = %proj; + %flipflop.projector.holo = 0; + break; + } + } +} + +//****************************************************************************** +//* DefaultGame Trigger - Functions * +//****************************************************************************** + +/// -Trigger- ////////////////////////////////////////////////////////////////// +//Function -- onEnterTrigger (%game, %name, %data, %obj, %colObj) +// %game = Current game type object +// %name = Trigger name - defined when trigger is created +// %data = Trigger Data Block +// %obj = Trigger Object +// %colObj = Object that collided with the trigger +//Decription -- Called when trigger has been triggered +//////////////////////////////////////////////////////////////////////////////// +// from 'trigger.cs' +function DefaultGame::onEnterTrigger(%game, %triggerName, %data, %obj, %colobj) +{ + //Do Nothing +} + +/// -Trigger- ////////////////////////////////////////////////////////////////// +//Function -- onLeaveTrigger (%game, %name, %data, %obj, %colObj) +// %game = Current game type object +// %name = Trigger name - defined when trigger is created +// %data = Trigger Data Block +// %obj = Trigger Object +// %colObj = Object that collided with the trigger +//Decription -- Called when trigger has been untriggered +//////////////////////////////////////////////////////////////////////////////// +// from 'trigger.cs' +function DefaultGame::onLeaveTrigger(%game, %triggerName, %data, %obj, %colobj) +{ + //Do Nothing +} + +/// -Trigger- ////////////////////////////////////////////////////////////////// +//Function -- onTickTrigger(%game, %name, %data, %obj) +// %game = Current game type object +// %name = Trigger name - defined when trigger is created +// %data = Trigger Data Block +// %obj = Trigger Object +//Decription -- Called every tick if triggered +//////////////////////////////////////////////////////////////////////////////// +// from 'trigger.cs' +function DefaultGame::onTickTrigger(%game, %triggerName, %data, %obj) +{ + //Do Nothing +} + + +function DefaultGame::setUpTeams(%game) +{ + %group = nameToID("MissionGroup/Teams"); + if(%group == -1) + return; + + // create a team0 if it does not exist + %team = nameToID("MissionGroup/Teams/team0"); + if(%team == -1) + { + %team = new SimGroup("team0"); + %group.add(%team); + } + + // 'team0' is not counted as a team here + %game.numTeams = 0; + while(%team != -1) + { + // create drop set and add all spawnsphere objects into it + %dropSet = new SimSet("TeamDrops" @ %game.numTeams); + MissionCleanup.add(%dropSet); + + %spawns = nameToID("MissionGroup/Teams/team" @ %game.numTeams @ "/SpawnSpheres"); + if(%spawns != -1) + { + %count = %spawns.getCount(); + for(%i = 0; %i < %count; %i++) + %dropSet.add(%spawns.getObject(%i)); + } + + // set the 'team' field for all the objects in this team + %team.setTeam(%game.numTeams); + + clearVehicleCount(%team+1); + // get next group + %team = nameToID("MissionGroup/Teams/team" @ %game.numTeams + 1); + if (%team != -1) + %game.numTeams++; + } + + // set the number of sensor groups (including team0) that are processed + setSensorGroupCount(%game.numTeams + 1); +} + +function SimGroup::setTeam(%this, %team) +{ + for (%i = 0; %i < %this.getCount(); %i++) + { + %obj = %this.getObject(%i); + switch$ (%obj.getClassName()) + { + case SpawnSphere : + if($MatchStarted) + { + // find out what team the spawnsphere used to belong to + %found = false; + for(%l = 1; %l <= Game.numTeams; %l++) + { + %drops = nameToId("MissionCleanup/TeamDrops" @ %l); + for(%j = 0; %j < %drops.getCount(); %j++) + { + %current = %drops.getObject(%j); + if(%current == %obj) + %found = %l; + } + } + if(%team != %found) + Game.claimSpawn(%obj, %team, %found); + else + error("spawn "@%obj@" is already on team "@%team@"!"); + } + else + Game.claimSpawn(%obj, %team, ""); + case SimGroup : %obj.setTeam(%team); + default : %obj.team = %team; + } + + if(%obj.getType() & $TypeMasks::GameBaseObjectType) + { + // eeck.. please go away when scripts get cleaned... + // ----------------------------------------------------------------------------- + // z0dd - ZOD, 5/8/02. Part of re-write of Vehicle + // station creation. Do not need this code anymore. + //if(%obj.getDataBlock().getName() $= "StationVehiclePad") + //{ + // %team = %obj.team; + // %obj = %obj.station; + // %obj.team = %team; + //%obj.teleporter.team = %team; + //} + %target = %obj.getTarget(); + if(%target != -1) + setTargetSensorGroup(%target, %team); + } + } +} + +function DefaultGame::claimSpawn(%game, %obj, %newTeam, %oldTeam) +{ + if(%newTeam == %oldTeam) + return; + + %newSpawnGroup = nameToId("MissionCleanup/TeamDrops" @ %newTeam); + if(%oldTeam !$= "") + { + %oldSpawnGroup = nameToId("MissionCleanup/TeamDrops" @ %oldTeam); + %oldSpawnGroup.remove(%obj); + } + %newSpawnGroup.add(%obj); +} + +// recursive function to assign teams to all mission objects + +function SimGroup::swapTeams(%this) +{ + // used in Siege only + Game.groupSwapTeams(%this); +} + +function ShapeBase::swapTeams(%this) +{ + // used in Siege only + Game.objectSwapTeams(%this); +} + +function GameBase::swapTeams(%this) +{ + // used in Siege only + Game.objectSwapTeams(%this); +} + +function TSStatic::swapTeams(%this) +{ + // used in Siege only + // do nothing +} + +function InteriorInstance::swapTeams(%this) +{ + // used in Siege only + // do nothing -- interiors don't switch teams +} + +function SimGroup::swapVehiclePads(%this) +{ + // used in Siege only + Game.groupSwapVehiclePads(%this); +} + +function ShapeBase::swapVehiclePads(%this) +{ + // used in Siege only + Game.objectSwapVehiclePads(%this); +} + +function GameBase::swapVehiclePads(%this) +{ + // used in Siege only + // do nothing -- only searching for vehicle pads +} + +function InteriorInstance::swapVehiclePads(%this) +{ + // used in Siege only + // do nothing -- only searching for vehicle pads +} + +function SimSet::swapVehiclePads(%this) +{ + // used in Siege only + // do nothing -- only searching for vehicle pads +} + +function PhysicalZone::swapVehiclePads(%this) +{ + // used in Siege only + // do nothing -- only searching for vehicle pads +} + +function SimGroup::objectRestore(%this) +{ + // used in Siege only + Game.groupObjectRestore(%this); +} + +function ShapeBase::objectRestore(%object) +{ + // only used for Siege + Game.shapeObjectRestore(%object); +} + +function Turret::objectRestore(%object) +{ + // only used for Siege + Game.shapeObjectRestore(%object); +} + +function AIObjective::objectRestore(%object) +{ + // only used for Siege + // don't do anything for AI Objectives +} + +function DefaultGame::checkObjectives(%game) +{ + //any special objectives that can be met by gametype + //none for default game +} + +//--------------------------------------------------- + +function DefaultGame::checkTimeLimit(%game, %forced) +{ + // Don't add extra checks: + if ( %forced ) + cancel( %game.timeCheck ); + + // if there is no time limit, check back in a minute to see if it's been set + if(($Host::TimeLimit $= "") || $Host::TimeLimit == 0) + { + %game.timeCheck = %game.schedule(20000, "checkTimeLimit"); + return; + } + + %curTimeLeftMS = ($Host::TimeLimit * 60 * 1000) + $missionStartTime - getSimTime(); + + if (%curTimeLeftMS <= 0) + { + // time's up, put down your pencils + %game.timeLimitReached(); + } + else + { + if(%curTimeLeftMS >= 20000) + %game.timeCheck = %game.schedule(20000, "checkTimeLimit"); + else + %game.timeCheck = %game.schedule(%curTimeLeftMS + 1, "checkTimeLimit"); + + //now synchronize everyone's clock + messageAll('MsgSystemClock', "", $Host::TimeLimit, %curTimeLeftMS); + } +} + +function listplayers() +{ + for(%i = 0; %i < ClientGroup.getCount(); %i++) + { + %cl = ClientGroup.getObject(%i); + %status = ""; + if(%cl.isAiControlled()) + %status = "Bot "; + if(%cl.isSmurf) + %status = "Alias "; + if(%cl.isAdmin) + %status = %status @ "Admin "; + if(%cl.isSuperAdmin) + %status = %status @ "SuperAdmin "; + if(%status $= "") + %status = ""; + echo("client: " @ %cl @ " player: " @ %cl.player @ " name: " @ %cl.nameBase @ " team: " @ %cl.team @ " status: " @ %status); + } +} + +function DefaultGame::clearTeamRankArray(%game, %team) +{ + %count = $TeamRank[%team, count]; + for (%i = 0; %i < %count; %i++) + $TeamRank[%team, %i] = ""; + $TeamRank[%team, count] = 0; +} + +function DefaultGame::populateTeamRankArray(%game, %client) +{ + //this function should be called *after* the client has been added to a team... + if (%client <= 0 || %client.team <= 0) + return; + + //find the team + if (%game.numTeams == 1) + %team = 0; + else + %team = %client.team; + + //find the number of teammates already ranked... + %count = $TeamRank[%team, count]; + if (%count $= "") + { + $TeamRank[%team, count] = 0; + %count = 0; + } + + //make sure we're not already in the array + for (%i = 0; %i < %count; %i++) + { + if ($TeamRank[%team, %i] == %client) + return; + } + + //add the client in at the bottom of the list, and increment the count + $TeamRank[%team, %count] = %client; + $TeamRank[%team, count] = $TeamRank[%team, count] + 1; + + //now recalculate the team rank for this player + %game.recalcTeamRanks(%client); +} + +function DefaultGame::removeFromTeamRankArray(%game, %client) +{ + //note, this should be called *before* the client actually switches teams or drops... + if (%client <= 0 || %client.team <= 0) + return; + + //find the correct team + if (%game.numTeams == 1) + %team = 0; + else + %team = %client.team; + + //now search throught the team rank array, looking for this client + %count = $TeamRank[%team, count]; + for (%i = 0; %i < %count; %i++) + { + if ($TeamRank[%team, %i] == %client) + { + //we've found the client in the array, now loop through, and move everyone else up a rank + for (%j = %i + 1; %j < %count; %j++) + { + %cl = $TeamRank[%team, %j]; + $TeamRank[%team, %j - 1] = %cl; + messageClient(%cl, 'MsgYourRankIs', "", %j); + } + $TeamRank[%team, %count - 1] = ""; + + //now decrement the team rank array count, and break + $TeamRank[%team, count] = $TeamRank[%team, count] - 1; + break; + } + } +} + +function DefaultGame::recalcTeamRanks(%game, %client) +{ + if (%client <= 0 || %client.team <= 0) + return; + + // this is a little confusing -- someone's actual numerical rank is always + // one number higher than his index in the $TeamRank array + // (e.g. person ranked 1st has index of 0) + + // TINMAN: I'm going to remove the %client.teamRank field - the index in the + // $TeamRank array already contains their rank - safer to search the array than + // to maintiain the information in a separate variable... + + //find the team, the client in the team array + if (%game.numTeams == 1) + %team = 0; + else + %team = %client.team; + + %count = $TeamRank[%team, count]; + %index = -1; + for (%i = 0; %i < %count; %i++) + { + if ($TeamRank[%team, %i] == %client) + { + %index = %i; + break; + } + } + + //if they weren't found in the array, return + if (%index < 0) + return; + + //make sure far down the array as they should be... + %tempIndex = %index; + %swapped = false; + while (true) + { + if (%tempIndex <= 0) + break; + + %tempIndex--; + %tempClient = $TeamRank[%team, %tempIndex]; + + //see if we should swap the two + if (%client.score > %tempClient.score) + { + %swapped = true; + %index = %tempIndex; + $TeamRank[%team, %tempIndex] = %client; + $TeamRank[%team, %tempIndex + 1] = %tempClient; + messageClient(%tempClient, 'MsgYourRankIs', "", %tempIndex + 2); + } + } + + //if we've swapped up at least once, we obviously won't need to swap down as well... + if (%swapped) + { + messageClient(%client, 'MsgYourRankIs', "", %index + 1); + return; + } + + //since we didnt' swap up, see if we need to swap down... + %tempIndex = %index; + %swapped = false; + while (true) + { + if (%tempIndex >= %count - 1) + break; + + %tempIndex++; + %tempClient = $TeamRank[%team, %tempIndex]; + + //see if we should swap the two + if (%client.score < %tempClient.score) + { + %swapped = true; + %index = %tempIndex; + $TeamRank[%team, %tempIndex] = %client; + $TeamRank[%team, %tempIndex - 1] = %tempClient; + messageClient(%tempClient, 'MsgYourRankIs', "", %tempIndex); + } + } + + //send the message (regardless of whether a swap happened or not) + messageClient(%client, 'MsgYourRankIs', "", %index + 1); +} + +function DefaultGame::recalcScore(%game, %cl) +{ + %game.recalcTeamRanks(%cl); +} + +function DefaultGame::testKill(%game, %victimID, %killerID) +{ + return ((%killerID !=0) && (%victimID.team != %killerID.team)); +} + +function DefaultGame::testSuicide(%game, %victimID, %killerID, %damageType) +{ + return ((%victimID == %killerID) || (%damageType == $DamageType::Ground) || (%damageType == $DamageType::Suicide)); +} + +function DefaultGame::testTeamKill(%game, %victimID, %killerID) +{ + return (%killerID.team == %victimID.team); +} + +function DefaultGame::testTurretKill(%game, %implement) +{ + if(%implement == 0) + return false; + else + return (%implement.getClassName() $= "Turret"); +} + +// function DefaultGame::awardScoreFlagCap(%game, %cl) +// { +// %cl.flagCaps++; +// $TeamScore[%cl.team] += %game.SCORE_PER_TEAM_FLAG_CAP; +// messageAll('MsgCTFTeamScore', "", %cl.team, $TeamScore[%cl.team]); +// +// if (%game.SCORE_PER_PLYR_FLAG_CAP > 1) +// %plural = "s"; +// else +// %plural = ""; +// +// if (%game.SCORE_PER_PLYR_FLAG_CAP != 0) +// messageClient(%cl, 'scoreFlaCapMsg', 'You received %1 point%2 for capturing the flag.', %game.SCORE_PER_PLYR_FLAG_CAP, %plural); +// %game.recalcScore(%cl); +// } + + +function DefaultGame::testOOBDeath(%game, %damageType) +{ + return (%damageType == $DamageType::OutOfBounds); +} + +function DefaultGame::awardScoreTurretKill(%game, %victimID, %implement) +{ + if ((%killer = %implement.getControllingClient()) != 0) //award whoever might be controlling the turret + { + if (%killer == %victimID) + %game.awardScoreSuicide(%victimID); + else if (%killer.team == %victimID.team) //player controlling a turret killed a teammate + { + %killer.teamKills++; + %game.awardScoreTurretTeamKill(%victimID, %killer); + %game.awardScoreDeath(%victimID); + } + else + { + %killer.turretKills++; + %game.recalcScore(%killer); + %game.awardScoreDeath(%victimID); + } + } + else if ((%killer = %implement.getOwner()) != 0) //if it isn't controlled, award score to whoever deployed it + { + if (%killer.team == %victimID.team) + { + %game.awardScoreDeath(%victimID); + } + else + { + %killer.turretKills++; + %game.recalcScore(%killer); + %game.awardScoreDeath(%victimID); + } + } + //default is, no one was controlling it, no one owned it. No score given. +} + +function DefaultGame::awardScoreDeath(%game, %victimID) +{ + %victimID.deaths++; + if ( %game.SCORE_PER_DEATH != 0 ) + { +// %plural = (abs(%game.SCORE_PER_DEATH) != 1 ? "s" : ""); +// messageClient(%victimID, 'MsgScoreDeath', '\c0You have been penalized %1 point%2 for dying.', abs(%game.SCORE_PER_DEATH), %plural); + %game.recalcScore(%victimID); + } +} + +function DefaultGame::awardScoreKill(%game, %killerID) +{ + %killerID.kills++; + %game.recalcScore(%killerID); +} + +function DefaultGame::awardScoreSuicide(%game, %victimID) +{ + %victimID.suicides++; +// if (%game.SCORE_PER_SUICIDE != 0) +// messageClient(%victimID, 'MsgScoreSuicide', '\c0You have been penalized for killing yourself.'); + %game.recalcScore(%victimID); +} + +function DefaultGame::awardScoreTeamkill(%game, %victimID, %killerID) +{ + %killerID.teamKills++; + if (%game.SCORE_PER_TEAMKILL != 0) + messageClient(%killerID, 'MsgScoreTeamkill', '\c0You have been penalized for killing teammate %1.', %victimID.name); + %game.recalcScore(%killerID); +} + +function DefaultGame::awardScoreTurretTeamKill(%game, %victimID, %killerID) +{ + %killerID.teamKills++; + if (%game.SCORE_PER_TEAMKILL != 0) + messageClient(%killerID, 'MsgScoreTeamkill', '\c0You have been penalized for killing your teammate %1, with a turret.', %victimID.name); + %game.recalcScore(%killerID); +} + + +function DefaultGame::objectRepaired(%game, %obj, %objName) +{ + %item = %obj.getDataBlock().getName(); + //echo("Item repaired is a " @ %item); + switch$ (%item) + { + case generatorLarge : + %game.genOnRepaired(%obj, %objName); + case stationInventory : + %game.stationOnRepaired(%obj, %objName); + case sensorMediumPulse : + %game.sensorOnRepaired(%obj, %objName); + case sensorLargePulse : + %game.sensorOnRepaired(%obj, %objName); + case turretBaseLarge : + %game.turretOnRepaired(%obj, %objName); + case stationVehicle : %game.vStationOnRepaired(%obj, %objName); + default: //unused by current gametypes. Add more checks here if desired + } +} + +function DefaultGame::allowsProtectedStatics(%game) +{ + return false; +} + +// jff: why is game object doing this? +//Return a simple string with no extras +function DefaultGame::cleanWord(%game, %this) +{ + %length = strlen(%this); + for(%i = 0; %i < %length; %i++) + { + %char = getSubStr(%this, %i, 1); + if(%char $= "_") + { + %next = getSubStr(%this, (%i+1), 1); + if(%next $= "_") + { + %char = "'"; //apostrophe (2 chars) + %i++; + } + else + %char = " "; //space + } + %clean = (%clean @ %char); + } +} + +function DefaultGame::stationOnEnterTrigger(%game, %data, %obj, %colObj) +{ + return true; +} + +function DefaultGame::WeaponOnUse(%game, %data, %obj) +{ + return true; +} + +function DefaultGame::HandInvOnUse(%game, %data, %obj) +{ + return true; +} + +function DefaultGame::WeaponOnInventory(%game, %this, %obj, %amount) +{ + return true; +} + +function DefaultGame::ObserverOnTrigger(%game, %data, %obj, %trigger, %state) +{ + return true; +} + +// jff: why is the game being notified that a weapon is being thrown? hot potato gametype? +function DefaultGame::ShapeThrowWeapon(%game, %this) +{ + return true; +} + +function DefaultGame::leaveMissionArea(%game, %playerData, %player) +{ + if(%player.getState() $= "Dead") + return; + + %player.client.outOfBounds = true; + messageClient(%player.client, 'LeaveMissionArea', '\c1You left the mission area.~wfx/misc/warning_beep.wav'); +} + +function DefaultGame::enterMissionArea(%game, %playerData, %player) +{ + if(%player.getState() $= "Dead") + return; + + %player.client.outOfBounds = false; + messageClient(%player.client, 'EnterMissionArea', '\c1You are back in the mission area.'); +} + +//------------------------------------------------------------------------------ +// AI stubs: +//------------------------------------------------------------------------------ + +function DefaultGame::onAIDamaged(%game, %clVictim, %clAttacker, %damageType, %sourceObject) +{ +} + +function DefaultGame::onAIFriendlyFire(%game, %clVictim, %clAttacker, %damageType, %sourceObject) +{ +} + +function DefaultGame::onAIKilled(%game, %clVictim, %clKiller, %damageType, %implement) +{ + //unassign the client from any objectives + AIUnassignClient(%clVictim); + + //break the link, if this ai is controlled + aiReleaseHumanControl(%clVictim.controlByHuman, %clVictim); + + //and schedule the respawn + %clVictim.respawnThread = schedule(5000, %clVictim, "onAIRespawn", %clVictim); +} + +function DefaultGame::onAIKilledClient(%game, %clVictim, %clAttacker, %damageType, %implement) +{ + %clAttacker.setVictim(%clVictim, %clVictim.player); +} + +//------------------------------------------------------------------------------ +// Voting stuff: +//------------------------------------------------------------------------------ +function DefaultGame::sendGamePlayerPopupMenu( %game, %client, %targetClient, %key ) +{ + if( !%targetClient.matchStartReady ) + return; + + %isAdmin = ( %client.isAdmin || %client.isSuperAdmin ); + + %isTargetSelf = ( %client == %targetClient ); + %isTargetAdmin = ( %targetClient.isAdmin || %targetClient.isSuperAdmin ); + %isTargetBot = %targetClient.isAIControlled(); + %isTargetObserver = ( %targetClient.team == 0 ); + %outrankTarget = false; + if ( %client.isSuperAdmin ) + %outrankTarget = !%targetClient.isSuperAdmin; + else if ( %client.isAdmin ) + %outrankTarget = !%targetClient.isAdmin; + + if( %client.isSuperAdmin && %targetClient.guid != 0 && !isDemo() ) + { + messageClient( %client, 'MsgPlayerPopupItem', "", %key, "addAdmin", "", 'Add to Server Admin List', 10); + messageClient( %client, 'MsgPlayerPopupItem', "", %key, "addSuperAdmin", "", 'Add to Server SuperAdmin List', 11); + } + + //mute options + if ( !%isTargetSelf ) + { + if ( %client.muted[%targetClient] ) + messageClient( %client, 'MsgPlayerPopupItem', "", %key, "MutePlayer", "", 'Unmute Text Chat', 1); + else + messageClient( %client, 'MsgPlayerPopupItem', "", %key, "MutePlayer", "", 'Mute Text Chat', 1); + + if ( !%isTargetBot && %client.canListenTo( %targetClient ) ) + { + if ( %client.getListenState( %targetClient ) ) + messageClient( %client, 'MsgPlayerPopupItem', "", %key, "ListenPlayer", "", 'Disable Voice Com', 9 ); + else + messageClient( %client, 'MsgPlayerPopupItem', "", %key, "ListenPlayer", "", 'Enable Voice Com', 9 ); + } + } + + if( !%client.canVote && !%isAdmin ) + return; + + // regular vote options on players + if ( %game.scheduleVote $= "" && !%isAdmin && !%isTargetAdmin ) + { + if ( $Host::allowAdminPlayerVotes && !%isTargetBot && !isDemo() ) + messageClient( %client, 'MsgPlayerPopupItem', "", %key, "AdminPlayer", "", 'Vote to Make Admin', 2 ); + + if ( !%isTargetSelf ) + { + messageClient( %client, 'MsgPlayerPopupItem', "", %key, "KickPlayer", "", 'Vote to Kick', 3 ); + } + } + + + // Admin only options on players: + else if ( %isAdmin && !isDemo() ) + { + if ( !%isTargetBot && !%isTargetAdmin ) + messageClient( %client, 'MsgPlayerPopupItem', "", %key, "AdminPlayer", "", 'Make Admin', 2 ); + + if ( !%isTargetSelf && %outrankTarget ) + { + messageClient( %client, 'MsgPlayerPopupItem', "", %key, "KickPlayer", "", 'Kick', 3 ); + + if ( !%isTargetBot ) + { + if( %client.isSuperAdmin ) + messageClient( %client, 'MsgPlayerPopupItem', "", %key, "BanPlayer", "", 'Ban', 4 ); + + if ( !%isTargetObserver ) + messageClient( %client, 'MsgPlayerPopupItem', "", %key, "ToObserver", "", 'Force observer', 5 ); + } + } + + + if ( %isTargetSelf || %outrankTarget ) + { + if ( %game.numTeams > 1 ) + { + if ( %isTargetObserver ) + { + %action = %isTargetSelf ? "Join " : "Change to "; + %str1 = %action @ getTaggedString( %game.getTeamName(1) ); + %str2 = %action @ getTaggedString( %game.getTeamName(2) ); + + messageClient( %client, 'MsgPlayerPopupItem', "", %key, "ChangeTeam", "", %str1, 6 ); + messageClient( %client, 'MsgPlayerPopupItem', "", %key, "ChangeTeam", "", %str2, 7 ); + } + else + { + %changeTo = %targetClient.team == 1 ? 2 : 1; + %str = "Switch to " @ getTaggedString( %game.getTeamName(%changeTo) ); + %caseId = 5 + %changeTo; + + messageClient( %client, 'MsgPlayerPopupItem', "", %key, "ChangeTeam", "", %str, %caseId ); + } + } + else if ( %isTargetObserver ) + { + %str = %isTargetSelf ? 'Join the Game' : 'Add to Game'; + messageClient( %client, 'MsgPlayerPopupItem', "", %key, "JoinGame", "", %str, 8 ); + } + } + } +} + +//------------------------------------------------------------------------------ +function DefaultGame::sendGameVoteMenu( %game, %client, %key ) +{ + %isAdmin = (%client.isAdmin || %client.isSuperAdmin); + %isSuperAdmin = (%client.isSuperAdmin); + %multipleTeams = %game.numTeams > 1; + + // jailed players do not need menus, unless they are admins + // Note that this does not block gametype-specific menus + if (%client.isJailed && !%isAdmin) + return; + + // no one is going anywhere until this thing starts + if($MatchStarted) + { + // Client options: + if ( %client.team != 0 ) + { + if ( %multipleTeams ) + if( !$Host::TournamentMode ) + messageClient( %client, 'MsgVoteItem', "", %key, 'ChooseTeam', "", 'Change your Team' ); + messageClient( %client, 'MsgVoteItem', "", %key, 'MakeObserver', "", 'Become an Observer' ); + } + else + { + if(!%multipleTeams && !$Host::TournamentMode) + messageClient( %client, 'MsgVoteItem', "", %key, 'JoinGame', "", 'Join the Game' ); + } + + //%totalSlots = $Host::maxPlayers - ($HostGamePlayerCount + $HostGameBotCount); + // if( $HostGameBotCount > 0 && %totalSlots > 0 && %isAdmin) + //messageClient( %client, 'MsgVoteItem', "", %key, 'Addbot', "", 'Add a Bot' ); + } + + if( !%client.canVote && !%isAdmin ) + return; + + if (isDemo()) + return; + + if ( %game.scheduleVote $= "" ) + { + if(!%isAdmin) + { + // Actual vote options: + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteChangeMission', 'change the mission to', 'Vote to Change the Mission' ); + + if( $Host::TournamentMode ) + { + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteFFAMode', 'Change server to Free For All.', 'Vote Free For All Mode' ); + + if(!$MatchStarted && !$CountdownStarted) + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteMatchStart', 'Start Match', 'Vote to Start the Match' ); + } + else + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteTournamentMode', 'Change server to Tournament.', 'Vote Tournament Mode' ); + + if ( %multipleTeams ) + { + if(!$MatchStarted && !$Host::TournamentMode) + messageClient( %client, 'MsgVoteItem', "", %key, 'ChooseTeam', "", 'Change your Team' ); + } + + if ( $teamDamage ) + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteTeamDamage', 'disable team damage', 'Vote to Disable Team Damage' ); + else + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteTeamDamage', 'enable team damage', 'Vote to Enable Team Damage' ); + + if ( $Host::Purebuild == 1 ) + messageClient( %client, 'MsgVoteItem', "", %key, 'VotePurebuild', 'disable pure building', '[\c1pure\c0] Vote to Disable Pure Building' ); + else + messageClient( %client, 'MsgVoteItem', "", %key, 'VotePurebuild', 'enable pure building', '[\c1pure\c0] Vote to Enable Pure Building' ); + if ( $Host::ExpertMode == 1) + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteExpertMode', 'disable expert mode', '[\c1pure\c0] Vote to Disable Expert Mode' ); + else + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteExpertMode', 'enable expert mode', '[\c1pure\c0] Vote to Enable Expert Mode' ); + } + else + { + // Actual vote options: + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteChangeMission', 'change the mission to', 'Change the Mission' ); + + if( $Host::TournamentMode ) + { + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteFFAMode', 'Change server to Free For All.', 'Free For All Mode' ); + + if(!$MatchStarted && !$CountdownStarted) + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteMatchStart', 'Start Match', 'Start Match' ); + } + else + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteTournamentMode', 'Change server to Tournament.', 'Tournament Mode' ); + + if ( %multipleTeams ) + { + if(!$MatchStarted) + messageClient( %client, 'MsgVoteItem', "", %key, 'ChooseTeam', "", 'Choose Team' ); + } + + if ( $teamDamage ) + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteTeamDamage', 'disable team damage', 'Disable Team Damage' ); + else + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteTeamDamage', 'enable team damage', 'Enable Team Damage' ); + + if ( $Host::Purebuild == 1 ) + messageClient( %client, 'MsgVoteItem', "", %key, 'VotePurebuild', 'disable pure building', '[\c1pure\c0] Disable Pure Building' ); + else + messageClient( %client, 'MsgVoteItem', "", %key, 'VotePurebuild', 'enable pure building', '[\c1pure\c0] Enable Pure Building' ); + } + } + + // Admin only options (plus some votable options :P) : + if ( %isAdmin ) { + if ( $Host::Cascade == 1) + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteCascadeMode', 'disable cascade mode', '[\c1pure\c0] Disable Cascade Mode' ); + else + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteCascadeMode', 'enable cascade mode', '[\c1pure\c0] Enable Cascade Mode' ); + if ( $Host::ExpertMode == 1) + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteExpertMode', 'disable expert mode', '[\c1pure\c0] Disable Expert Mode' ); + else + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteExpertMode', 'enable expert mode', '[\c1pure\c0] Enable Expert Mode' ); + if ( $Host::Vehicles == 1) + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteVehicles', 'disable vehicles', '[\c1pure\c0] Disable Vehicles' ); + else + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteVehicles', 'enable vehicles', '[\c1pure\c0] Enable Vehicles' ); + if ( $Host::InvincibleArmors == 1 ) + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteInvincibleArmors', 'disable invincible armors', '[\c1pure\c0] Disable Invincible Armors' ); + else + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteInvincibleArmors', 'enable invincible armors', '[\c1pure\c0] Enable Invincible Armors' ); + if ( $Host::InvincibleDeployables == 1 ) + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteInvincibleDeployables', 'disable invincible deployables', '[\c1pure\c0] Disable Invincible Deployables' ); + else + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteInvincibleDeployables', 'enable invincible deployables', '[\c1pure\c0] Enable Invincible Deployables' ); + if ( $Host::AllowUnderground == 1) + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteUndergroundMode', 'disable underground mode', '[\c1pure\c0] Disable Underground Mode' ); + else + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteUndergroundMode', 'enable underground mode', '[\c1pure\c0] Enable Underground Mode' ); + if ( $Host::Hazard::Enabled == 1 ) + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteHazardMode', 'disable hazard mode', '[\c1hazard\c0] Disable Hazard Mode' ); + else + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteHazardMode', 'enable hazard mode', '[\c1hazard\c0] Enable Hazard Mode' ); + if ($MTC_Loaded == 1) { + if ( $Host::MTC::Enabled == 1 ) + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteMTCMode', 'disable MTC mode', '[\c1mtc\c0] Disable MTC Mode' ); + else + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteMTCMode', 'enable MTC mode', '[\c1mtc\c0] Enable MTC Mode' ); + } + if ( $Host::SatchelChargeEnabled == 1 ) + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteSatchelCharge', 'disable satchel charges', '[\c1security\c0] Disable Satchel Charges' ); + else + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteSatchelCharge', 'enable satchel charges', '[\c1security\c0] Enable Satchel Charges' ); + if ( $Host::OnlyOwnerDeconstruct == 1 ) + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteOnlyOwnerDeconstruct', 'disable only owner deconstruct', '[\c1security\c0] Disable Only Owner Deconstruct' ); + else + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteOnlyOwnerDeconstruct', 'enable only owner deconstruct', '[\c1security\c0] Enable Only Owner Deconstruct' ); + if ( $Host::OnlyOwnerCascade == 1 ) + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteOnlyOwnerCascade', 'disable only owner cascade', '[\c1security\c0] Disable Only Owner Cascade' ); + else + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteOnlyOwnerCascade', 'enable only owner cascade', '[\c1security\c0] Enable Only Owner Cascade' ); + if ( $Host::OnlyOwnerRotate == 1 ) + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteOnlyOwnerRotate', 'disable only owner rotate', '[\c1security\c0] Disable Only Owner Rotate' ); + else + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteOnlyOwnerRotate', 'enable only owner rotate', '[\c1security\c0] Enable Only Owner Rotate' ); + if ( $Host::OnlyOwnerCubicReplace == 1 ) + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteOnlyOwnerCubicReplace', 'disable only owner cubic-replace', '[\c1security\c0] Disable Only Owner Cubic-Replace' ); + else + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteOnlyOwnerCubicReplace', 'enable only owner cubic-replace', '[\c1security\c0] Enable Only Owner Cubic-Replace' ); + if ( $Host::Prison::Enabled == 1 ) + messageClient( %client, 'MsgVoteItem', "", %key, 'VotePrison', 'disable prison', '[\c1prison\c0] Disable Prison' ); + else + messageClient( %client, 'MsgVoteItem', "", %key, 'VotePrison', 'enable prison', '[\c1prison\c0] Enable Prison' ); + if ( $Host::Prison::Enabled == 1 ) { + if ( $Host::Prison::Kill == 1 ) + messageClient( %client, 'MsgVoteItem', "", %key, 'VotePrisonKilling', 'disable jailing killers', '[\c1prison\c0] Disable Jailing of Killers' ); + else + messageClient( %client, 'MsgVoteItem', "", %key, 'VotePrisonKilling', 'enable jailing killers', '[\c1prison\c0] Enable Jailing of Killers' ); + if ( $Host::Prison::TeamKill == 1 ) + messageClient( %client, 'MsgVoteItem', "", %key, 'VotePrisonTeamKilling', 'disable jailing team killers', '[\c1prison\c0] Disable Jailing of Team Killers' ); + else + messageClient( %client, 'MsgVoteItem', "", %key, 'VotePrisonTeamKilling', 'enable jailing team killers', '[\c1prison\c0] Enable Jailing of Team Killers' ); + if ( $Host::Prison::DeploySpam == 1 ) + messageClient( %client, 'MsgVoteItem', "", %key, 'VotePrisonDeploySpam', 'disable jailing deploy spammers', '[\c1prison\c0] Disable Jailing of Deploy Spammers'); + else + messageClient( %client, 'MsgVoteItem', "", %key, 'VotePrisonDeploySpam', 'enable jailing deploy spammers', '[\c1prison\c0] Enable Jailing of Deploy Spammers' ); + } + if ($Host::Nerf::Enabled == 1) + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteNerfWeapons', 'disable nerf weapons', '[\c1nerf\c0] Disable Nerf Weapons' ); + else + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteNerfWeapons', 'enable nerf weapons', '[\c1nerf\c0] Enable Nerf Weapons' ); + if ($Host::Nerf::Enabled == 1) { + if ( $Host::Nerf::DanceAnim == 1 && $Host::Nerf::DeathAnim == 0 ) + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteNerfDance', 'disable nerf dance mode', '[\c1nerf\c0] Disable Nerf Dance Mode' ); + else + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteNerfDance', 'enable nerf dance mode', '[\c1nerf\c0] Enable Nerf Dance Mode' ); + if ( $Host::Nerf::DeathAnim == 1 ) + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteNerfDeath', 'disable nerf death mode', '[\c1nerf\c0] Disable Nerf Death Mode' ); + else + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteNerfDeath', 'enable nerf death mode', '[\c1nerf\c0] Enable Nerf Death Mode' ); + if ($Host::Prison::Enabled == 1) { + if ( $Host::Nerf::Prison == 1 ) + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteNerfPrison', 'disable nerf prison mode', '[\c1nerf\c0] Disable Nerf Prison Mode' ); + else + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteNerfPrison', 'enable nerf prison mode', '[\c1nerf\c0] Enable Nerf Prison Mode' ); + } + } + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteGlobalPowerCheck', 'evaluate power for all deployables', '[\c1power\c0] Evaluate Power for All Deployables' ); + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteRemoveDupDeployables', 'remove all duplicate deployables', '[\c4spam\c0] Remove All Duplicate Deployables' ); + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteRemoveNonPoweredDeployables', 'remove all deployables without power', '[\c4spam\c0] Remove All Deployables Without Power' ); + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteRemoveOrphanedDeployables', 'remove all orphaned deployables', '[\c4spam\c0] Remove All Orphaned Deployables' ); + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteRemoveDeployables', 'remove all deployables in mission', '[\c4spam\c0] Remove All Deployables In Mission' ); + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteChangeTimeLimit', 'change the time limit', 'Change the Time Limit' ); + messageClient( %client, 'MsgVoteItem', "", %key, 'VoteResetServer', 'reset server defaults', 'Reset the Server' ); + } +} + +//------------------------------------------------------------------------------ +function DefaultGame::sendGameTeamList( %game, %client, %key ) +{ + %teamCount = %game.numTeams; + if ( %teamCount < 2 ) + { + warn( "Team menu requested for one-team game!" ); + return; + } + + for ( %team = 1; %team - 1 < %teamCount; %team++ ) + messageClient( %client, 'MsgVoteItem', "", %key, %team, "", detag( getTaggedString( %game.getTeamName(%team) ) ) ); +} + +//------------------------------------------------------------------------------ +function DefaultGame::sendTimeLimitList( %game, %client, %key ) +{ + messageClient( %client, 'MsgVoteItem', "", %key, 10, "", '10 minutes' ); + messageClient( %client, 'MsgVoteItem', "", %key, 15, "", '15 minutes' ); + messageClient( %client, 'MsgVoteItem', "", %key, 20, "", '20 minutes' ); + messageClient( %client, 'MsgVoteItem', "", %key, 25, "", '25 minutes' ); + messageClient( %client, 'MsgVoteItem', "", %key, 30, "", '30 minutes' ); + messageClient( %client, 'MsgVoteItem', "", %key, 45, "", '45 minutes' ); + messageClient( %client, 'MsgVoteItem', "", %key, 60, "", '60 minutes' ); + messageClient( %client, 'MsgVoteItem', "", %key, 10080, "", 'No time limit' ); +} + +//------------------------------------------------------------------------------ +// all global votes here +// this function was created to remove the call to "eval", which is non-functional in PURE servers... +function DefaultGame::evalVote(%game, %typeName, %admin, %arg1, %arg2, %arg3, %arg4) +{ + switch$ (%typeName) + { + case "voteChangeMission": + %game.voteChangeMission(%admin, %arg1, %arg2, %arg3, %arg4); + case "voteTeamDamage": + %game.voteTeamDamage(%admin, %arg1, %arg2, %arg3, %arg4); + case "voteTournamentMode": + %game.voteTournamentMode(%admin, %arg1, %arg2, %arg3, %arg4); + case "voteMatchStart": + %game.voteMatchStart(%admin, %arg1, %arg2, %arg3, %arg4); + case "voteFFAMode": + %game.voteFFAMode(%admin, %arg1, %arg2, %arg3, %arg4); + case "voteChangeTimeLimit": + %game.voteChangeTimeLimit(%admin, %arg1, %arg2, %arg3, %arg4); + case "voteResetServer": + %game.voteResetServer(%admin, %arg1, %arg2, %arg3, %arg4); + case "voteKickPlayer": + %game.voteKickPlayer(%admin, %arg1, %arg2, %arg3, %arg4); + case "voteAdminPlayer": + %game.voteAdminPlayer(%admin, %arg1, %arg2, %arg3, %arg4); + case "voteGreedMode": + %game.voteGreedMode(%admin, %arg1, %arg2, %arg3, %arg4); + case "voteHoardMode": + %game.voteHoardMode(%admin, %arg1, %arg2, %arg3, %arg4); + case "votePurebuild": + %game.votePurebuild(%admin, %arg1, %arg2, %arg3, %arg4); + case "voteCascadeMode": + %game.voteCascadeMode(%admin, %arg1, %arg2, %arg3, %arg4); + case "voteExpertMode": + %game.voteExpertMode(%admin, %arg1, %arg2, %arg3, %arg4); + case "VoteVehicles": + %game.VoteVehicles(%admin, %arg1, %arg2, %arg3, %arg4); + case "voteInvincibleArmors": + %game.voteInvincibleArmors(%admin, %arg1, %arg2, %arg3, %arg4); + case "voteInvincibleDeployables": + %game.voteInvincibleDeployables(%admin, %arg1, %arg2, %arg3, %arg4); + case "voteUndergroundMode": + %game.voteUndergroundMode(%admin, %arg1, %arg2, %arg3, %arg4); + case "voteHazardMode": + %game.voteHazardMode(%admin, %arg1, %arg2, %arg3, %arg4); + case "voteMTCMode": + %game.voteMTCMode(%admin, %arg1, %arg2, %arg3, %arg4); + case "voteSatchelCharge": + %game.voteSatchelCharge(%admin, %arg1, %arg2, %arg3, %arg4); + case "voteOnlyOwnerDeconstruct": + %game.voteOnlyOwnerDeconstruct(%admin, %arg1, %arg2, %arg3, %arg4); + case "voteOnlyOwnerCascade": + %game.voteOnlyOwnerCascade(%admin, %arg1, %arg2, %arg3, %arg4); + case "voteOnlyOwnerRotate": + %game.voteOnlyOwnerRotate(%admin, %arg1, %arg2, %arg3, %arg4); + case "voteOnlyOwnerCubicReplace": + %game.voteOnlyOwnerCubicReplace(%admin, %arg1, %arg2, %arg3, %arg4); + case "votePrison": + %game.votePrison(%admin, %arg1, %arg2, %arg3, %arg4); + case "votePrisonKilling": + %game.VotePrisonKilling(%admin, %arg1, %arg2, %arg3, %arg4); + case "votePrisonTeamKilling": + %game.VotePrisonTeamKilling(%admin, %arg1, %arg2, %arg3, %arg4); + case "votePrisonDeploySpam": + %game.VotePrisonDeploySpam(%admin, %arg1, %arg2, %arg3, %arg4); + case "voteNerfWeapons": + %game.voteNerfWeapons(%admin, %arg1, %arg2, %arg3, %arg4); + case "voteNerfDance": + %game.voteNerfDance(%admin, %arg1, %arg2, %arg3, %arg4); + case "voteNerfDeath": + %game.voteNerfDeath(%admin, %arg1, %arg2, %arg3, %arg4); + case "voteNerfPrison": + %game.voteNerfPrison(%admin, %arg1, %arg2, %arg3, %arg4); + case "voteGlobalPowerCheck": + %game.voteGlobalPowerCheck(%admin, %arg1, %arg2, %arg3, %arg4); + case "voteRemoveDupDeployables": + %game.voteRemoveDupDeployables(%admin, %arg1, %arg2, %arg3, %arg4); + case "VoteRemoveNonPoweredDeployables": + %game.VoteRemoveNonPoweredDeployables(%admin, %arg1, %arg2, %arg3, %arg4); + case "VoteRemoveOrphanedDeployables": + %game.VoteRemoveOrphanedDeployables(%admin, %arg1, %arg2, %arg3, %arg4); + case "voteRemoveDeployables": + %game.voteRemoveDeployables(%admin, %arg1, %arg2, %arg3, %arg4); + } +} + +function DefaultGame::voteChangeMission(%game, %admin, %missionDisplayName, %typeDisplayName, %missionId, %missionTypeId) +{ + if (%admin) { + if (%missionTypeId $= "LoadBuildingFile") { + %file = stripChars(%missionDisplayName,":\\/"); + if (getSubStr(%file,0,1) $= "_") { + %dir = $SaveBuilding::AutoSaveFolder; + %file = getSubStr(%file,1,strLen(%file)-1); + } + else + %dir = "Buildings/Admin/"; + if (%file $= "") + return; + else { + if (strStr(%file,"..") != -1) + return; + } + %file = %dir @ %file; + if (isFile(%file) && getSubStr(%file,strLen(%file)-3,3) $= ".cs") { + // Message is sent first, so clients know what happened in case server crashes + messageAll('MsgAdminForce', '\c2The Admin has loaded a building file.'); + compile(%file); + exec(%file); + } + return; + } + } + + %mission = $HostMissionFile[%missionId]; + if ( %mission $= "" ) + { + error( "Invalid mission index passed to DefaultGame::voteChangeMission!" ); + return; + } + + %missionType = $HostTypeName[%missionTypeId]; + if ( %missionType $= "" ) + { + error( "Invalid mission type id passed to DefaultGame::voteChangeMission!" ); + return; + } + + if(%admin) + { + messageAll('MsgAdminChangeMission', '\c2The Admin has changed the mission to %1 (%2).', %missionDisplayName, %typeDisplayName ); + logEcho("mission changed to "@%missionDisplayName@"/"@%typeDisplayName@" (admin)"); + %game.gameOver(); + loadMission( %mission, %missionType, false ); + } + else + { + %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; + if(%totalVotes > 0 && (%game.totalVotesFor / (ClientGroup.getCount() - $HostGameBotCount)) > ($Host::VotePasspercent / 100)) + { + messageAll('MsgVotePassed', '\c2The mission was changed to %1 (%2) by vote.', %missionDisplayName, %typeDisplayName ); + logEcho("mission changed to "@%missionDisplayName@"/"@%typeDisplayName@" (vote)"); + %game.gameOver(); + loadMission( %mission, %missionType, false ); + } + else + messageAll('MsgVoteFailed', '\c2Change mission vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + } +} + +//------------------------------------------------------------------------------ +function DefaultGame::voteTeamDamage(%game, %admin) +{ + %setto = ""; + %cause = ""; + if(%admin) + { + if($teamDamage) + { + messageAll('MsgAdminForce', '\c2The Admin has disabled team damage.'); + $Host::TeamDamageOn = $TeamDamage = 0; + %setto = "disabled"; + } + else + { + messageAll('MsgAdminForce', '\c2The Admin has enabled team damage.'); + $Host::TeamDamageOn = $TeamDamage = 1; + %setto = "enabled"; + } + %cause = "(admin)"; + } + else + { + %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; + if(%totalVotes > 0 && (%game.totalVotesFor / (ClientGroup.getCount() - $HostGameBotCount)) > ($Host::VotePasspercent / 100)) + { + if($teamDamage) + { + messageAll('MsgVotePassed', '\c2Team damage was disabled by vote.'); + $Host::TeamDamageOn = $TeamDamage = 0; + %setto = "disabled"; + } + else + { + messageAll('MsgVotePassed', '\c2Team damage was enabled by vote.'); + $Host::TeamDamageOn = $TeamDamage = 1; + %setto = "enabled"; + } + %cause = "(vote)"; + } + else + { + if($teamDamage) + messageAll('MsgVoteFailed', '\c2Disable team damage vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + else + messageAll('MsgVoteFailed', '\c2Enable team damage vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + } + } + if(%setto !$= "") + logEcho("team damage "@%setto SPC %cause); +} + +//------------------------------------------------------------------------------ +function DefaultGame::votePurebuild(%game, %admin) +{ + %setto = ""; + %cause = ""; + if(%admin) + { + if($Host::Purebuild == 1) + { + messageAll('MsgAdminForce', '\c2The Admin has disabled pure building.'); + purebuildOff(); + %setto = "disabled"; + } + else + { + messageAll('MsgAdminForce', '\c2The Admin has enabled pure building.'); + purebuildOn(); + %setto = "enabled"; + } + %cause = "(admin)"; + } + else + { + %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; + if(%totalVotes > 0 && (%game.totalVotesFor / (ClientGroup.getCount() - $HostGameBotCount)) > ($Host::VotePasspercent / 100)) + { + if($Host::Purebuild == 1) + { + messageAll('MsgVotePassed', '\c2Pure building was disabled by vote.'); + purebuildOff(); + %setto = "disabled"; + } + else + { + messageAll('MsgVotePassed', '\c2Pure building was enabled by vote.'); + purebuildOn(); + %setto = "enabled"; + } + %cause = "(vote)"; + } + else + { + if($Host::Purebuild == 1) + messageAll('MsgVoteFailed', '\c2Disable pure building vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + else + messageAll('MsgVoteFailed', '\c2Enable pure building vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + } + } + if(%setto !$= "") + logEcho("purebuild "@%setto SPC %cause); +} + +//------------------------------------------------------------------------------ +function DefaultGame::voteCascadeMode(%game, %admin) +{ + %setto = ""; + %cause = ""; + if(%admin) + { + if($Host::Cascade == 1) + { + messageAll('MsgAdminForce', '\c2The Admin has disabled Cascade mode.'); + $Host::Cascade = 0; + %setto = "disabled"; + } + else + { + messageAll('MsgAdminForce', '\c2The Admin has enabled Cascade mode.'); + $Host::Cascade = 1; + %setto = "enabled"; + } + %cause = "(admin)"; + } + else + { + %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; + if(%totalVotes > 0 && (%game.totalVotesFor / (ClientGroup.getCount() - $HostGameBotCount)) > ($Host::VotePasspercent / 100)) + { + if($Host::Cascade == 1) + { + messageAll('MsgVotePassed', '\c2Cascade mode was disabled by vote.'); + $Host::Cascade = 0; + %setto = "disabled"; + } + else + { + messageAll('MsgVotePassed', '\c2Cascade mode was enabled by vote.'); + $Host::Cascade = 1; + %setto = "enabled"; + } + %cause = "(vote)"; + } + else + { + if($Host::Cascade == 1 && $Host::Cascade == 0) + messageAll('MsgVoteFailed', '\c2Disable Cascade mode vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + else + messageAll('MsgVoteFailed', '\c2Enable Cascade mode vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + } + } + if(%setto !$= "") + logEcho("cascade mode "@%setto SPC %cause); +} + +//------------------------------------------------------------------------------ +function DefaultGame::voteExpertMode(%game, %admin) +{ + %setto = ""; + %cause = ""; + if(%admin) + { + if($Host::ExpertMode == 1) + { + messageAll('MsgAdminForce', '\c2The Admin has disabled Expert mode.'); + expertModeOff(); + %setto = "disabled"; + } + else + { + messageAll('MsgAdminForce', '\c2The Admin has enabled Expert mode.'); + expertModeOn(); + %setto = "enabled"; + } + %cause = "(admin)"; + } + else + { + %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; + if(%totalVotes > 0 && (%game.totalVotesFor / (ClientGroup.getCount() - $HostGameBotCount)) > ($Host::VotePasspercent / 100)) + { + if($Host::ExpertMode == 1) + { + messageAll('MsgVotePassed', '\c2Expert mode was disabled by vote.'); + expertModeOff(); + %setto = "disabled"; + } + else + { + messageAll('MsgVotePassed', '\c2Expert mode was enabled by vote.'); + expertModeOn(); + %setto = "enabled"; + } + %cause = "(vote)"; + } + else + { + if($Host::ExpertMode == 1 && $Host::ExpertMode == 0) + messageAll('MsgVoteFailed', '\c2Disable Expert mode vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + else + messageAll('MsgVoteFailed', '\c2Enable Expert mode vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + } + } + if(%setto !$= "") + logEcho("expert mode "@%setto SPC %cause); +} + +//------------------------------------------------------------------------------ +function DefaultGame::VoteVehicles(%game, %admin) { + if (!(Game.pureVehTime < getSimTime())) + return; + + %setto = ""; + %cause = ""; + if(%admin) { + if($Host::Vehicles == 1) { + messageAll('MsgAdminForce', '\c2The Admin has disabled vehicles.'); + disableVehicles(); + Game.pureVehTime = getSimTime() + 5000; + %setto = "disabled"; + } + else { + messageAll('MsgAdminForce', '\c2The Admin has enabled vehicles.'); + enableVehicles(); + Game.pureVehTime = getSimTime() + 5000; + %setto = "enabled"; + } + %cause = "(admin)"; + } + else { + %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; + if(%totalVotes > 0 && (%game.totalVotesFor / (ClientGroup.getCount() - $HostGameBotCount)) > ($Host::VotePasspercent / 100)) { + if($Host::Vehicles == 1) { + messageAll('MsgVotePassed', '\c2Vehicles were disabled by vote.'); + disableVehicles(); + Game.pureVehTime = getSimTime() + 5000; + %setto = "disabled"; + } + else { + messageAll('MsgVotePassed', '\c2Vehicles were enabled by vote.'); + enableVehicles(); + Game.pureVehTime = getSimTime() + 5000; + %setto = "enabled"; + } + %cause = "(vote)"; + } + else { + if($Host::Vehicles == 1) + messageAll('MsgVoteFailed', '\c2Disable vehicles vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + else + messageAll('MsgVoteFailed', '\c2Enable vehicles vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + } + } + if(%setto !$= "") + logEcho("pure vehicles "@%setto SPC %cause); +} + +//------------------------------------------------------------------------------ +function DefaultGame::VoteSatchelCharge(%game, %admin) +{ + %setto = ""; + %cause = ""; + if(%admin) + { + if($Host::SatchelChargeEnabled == 1) + { + messageAll('MsgAdminForce', '\c2The Admin has disabled satchel charges.'); + $Host::SatchelChargeEnabled = 0; + %setto = "disabled"; + } + else + { + messageAll('MsgAdminForce', '\c2The Admin has enabled satchel charges.'); + $Host::SatchelChargeEnabled = 1; + %setto = "enabled"; + } + %cause = "(admin)"; + } + else + { + %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; + if(%totalVotes > 0 && (%game.totalVotesFor / (ClientGroup.getCount() - $HostGameBotCount)) > ($Host::VotePasspercent / 100)) + { + if($Host::SatchelChargeEnabled == 1) + { + messageAll('MsgVotePassed', '\c2Satchel charges was disabled by vote.'); + $Host::SatchelChargeEnabled = 0; + %setto = "disabled"; + } + else + { + messageAll('MsgVotePassed', '\c2Satchel charges was enabled by vote.'); + $Host::SatchelChargeEnabled = 1; + %setto = "enabled"; + } + %cause = "(vote)"; + } + else + { + if($Host::SatchelChargeEnabled == 1) + messageAll('MsgVoteFailed', '\c2Disable satchel charges vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + else + messageAll('MsgVoteFailed', '\c2Enable satchel charges vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + } + } + if(%setto !$= "") + logEcho("satchel charges "@%setto SPC %cause); +} + +//------------------------------------------------------------------------------ +function DefaultGame::VoteOnlyOwnerDeconstruct(%game, %admin) +{ + %setto = ""; + %cause = ""; + if(%admin) + { + if($Host::OnlyOwnerDeconstruct == 1) + { + messageAll('MsgAdminForce', '\c2The Admin has disabled only owner deconstruct mode.'); + $Host::OnlyOwnerDeconstruct = 0; + %setto = "disabled"; + } + else + { + messageAll('MsgAdminForce', '\c2The Admin has enabled only owner deconstruct mode.'); + $Host::OnlyOwnerDeconstruct = 1; + %setto = "enabled"; + } + %cause = "(admin)"; + } + else + { + %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; + if(%totalVotes > 0 && (%game.totalVotesFor / (ClientGroup.getCount() - $HostGameBotCount)) > ($Host::VotePasspercent / 100)) + { + if($Host::OnlyOwnerDeconstruct == 1) + { + messageAll('MsgVotePassed', '\c2Only owner deconstruct mode was disabled by vote.'); + $Host::OnlyOwnerDeconstruct = 0; + %setto = "disabled"; + } + else + { + messageAll('MsgVotePassed', '\c2Only owner deconstruct mode was enabled by vote.'); + $Host::OnlyOwnerDeconstruct = 1; + %setto = "enabled"; + } + %cause = "(vote)"; + } + else + { + if($Host::OnlyOwnerDeconstruct == 1) + messageAll('MsgVoteFailed', '\c2Only owner deconstruct vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + else + messageAll('MsgVoteFailed', '\c2Only owner deconstruct vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + } + } + if(%setto !$= "") + logEcho("only owner deconstruct "@%setto SPC %cause); +} + +//------------------------------------------------------------------------------ +function DefaultGame::VoteOnlyOwnerCascade(%game, %admin) +{ + %setto = ""; + %cause = ""; + if(%admin) + { + if($Host::OnlyOwnerCascade == 1) + { + messageAll('MsgAdminForce', '\c2The Admin has disabled only owner cascade mode.'); + $Host::OnlyOwnerCascade = 0; + %setto = "disabled"; + } + else + { + messageAll('MsgAdminForce', '\c2The Admin has enabled only owner cascade mode.'); + $Host::OnlyOwnerCascade = 1; + %setto = "enabled"; + } + %cause = "(admin)"; + } + else + { + %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; + if(%totalVotes > 0 && (%game.totalVotesFor / (ClientGroup.getCount() - $HostGameBotCount)) > ($Host::VotePasspercent / 100)) + { + if($Host::OnlyOwnerCascade == 1) + { + messageAll('MsgVotePassed', '\c2Only owner cascade mode was disabled by vote.'); + $Host::OnlyOwnerCascade = 0; + %setto = "disabled"; + } + else + { + messageAll('MsgVotePassed', '\c2Only owner cascade mode was enabled by vote.'); + $Host::OnlyOwnerCascade = 1; + %setto = "enabled"; + } + %cause = "(vote)"; + } + else + { + if($Host::OnlyOwnerCascade == 1) + messageAll('MsgVoteFailed', '\c2Only owner cascade vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + else + messageAll('MsgVoteFailed', '\c2Only owner cascade vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + } + } + if(%setto !$= "") + logEcho("only owner cascade "@%setto SPC %cause); +} + +//------------------------------------------------------------------------------ +function DefaultGame::VoteOnlyOwnerRotate(%game, %admin) +{ + %setto = ""; + %cause = ""; + if(%admin) + { + if($Host::OnlyOwnerRotate == 1) + { + messageAll('MsgAdminForce', '\c2The Admin has disabled only owner rotate mode.'); + $Host::OnlyOwnerRotate = 0; + %setto = "disabled"; + } + else + { + messageAll('MsgAdminForce', '\c2The Admin has enabled only owner rotate mode.'); + $Host::OnlyOwnerRotate = 1; + %setto = "enabled"; + } + %cause = "(admin)"; + } + else + { + %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; + if(%totalVotes > 0 && (%game.totalVotesFor / (ClientGroup.getCount() - $HostGameBotCount)) > ($Host::VotePasspercent / 100)) + { + if($Host::OnlyOwnerRotate == 1) + { + messageAll('MsgVotePassed', '\c2Only owner rotate mode was disabled by vote.'); + $Host::OnlyOwnerRotate = 0; + %setto = "disabled"; + } + else + { + messageAll('MsgVotePassed', '\c2Only owner rotate mode was enabled by vote.'); + $Host::OnlyOwnerRotate = 1; + %setto = "enabled"; + } + %cause = "(vote)"; + } + else + { + if($Host::OnlyOwnerRotate == 1) + messageAll('MsgVoteFailed', '\c2Only owner rotate vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + else + messageAll('MsgVoteFailed', '\c2Only owner rotate vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + } + } + if(%setto !$= "") + logEcho("only owner rotate "@%setto SPC %cause); +} + +//------------------------------------------------------------------------------ +function DefaultGame::VoteOnlyOwnerCubicReplace(%game, %admin) +{ + %setto = ""; + %cause = ""; + if(%admin) + { + if($Host::OnlyOwnerCubicReplace == 1) + { + messageAll('MsgAdminForce', '\c2The Admin has disabled only owner cubic-replace mode.'); + $Host::OnlyOwnerCubicReplace = 0; + %setto = "disabled"; + } + else + { + messageAll('MsgAdminForce', '\c2The Admin has enabled only owner cubic-replace mode.'); + $Host::OnlyOwnerCubicReplace = 1; + %setto = "enabled"; + } + %cause = "(admin)"; + } + else + { + %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; + if(%totalVotes > 0 && (%game.totalVotesFor / (ClientGroup.getCount() - $HostGameBotCount)) > ($Host::VotePasspercent / 100)) + { + if($Host::OnlyOwnerCubicReplace == 1) + { + messageAll('MsgVotePassed', '\c2Only owner cubic-replace mode was disabled by vote.'); + $Host::OnlyOwnerCubicReplace = 0; + %setto = "disabled"; + } + else + { + messageAll('MsgVotePassed', '\c2Only owner cubic-replace mode was enabled by vote.'); + $Host::OnlyOwnerCubicReplace = 1; + %setto = "enabled"; + } + %cause = "(vote)"; + } + else + { + if($Host::OnlyOwnerCubicReplace == 1) + messageAll('MsgVoteFailed', '\c2Only owner cubic-replace vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + else + messageAll('MsgVoteFailed', '\c2Only owner cubic-replace vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + } + } + if(%setto !$= "") + logEcho("only owner cubic-replace "@%setto SPC %cause); +} + +//------------------------------------------------------------------------------ +function DefaultGame::VoteGlobalPowerCheck( %game, %admin, %client ) { + %cause = ""; + if (%admin) { + messageAll( 'MsgAdminForce', '\c2The Admin has evaluated power for all deployables in the mission.' ); + globalPowerCheck(); + %cause = "(admin)"; + } + else { + %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; + if(%totalVotes > 0 && (%game.totalVotesFor / (ClientGroup.getCount() - $HostGameBotCount)) > ($Host::VotePasspercent / 100)) { + messageAll('MsgVotePassed', '\c2Evaluating power for all deployables in the mission by vote.' ); + globalPowerCheck(); + %cause = "(vote)"; + } + else + messageAll('MsgVoteFailed', '\c2The vote to evaluate power for all deployables in the mission did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + } + if(%cause !$= "") + logEcho("evaluate power for all deployables "@%cause); +} + +//------------------------------------------------------------------------------ +function DefaultGame::VoteRemoveDupDeployables( %game, %admin, %client ) { + if (!(Game.removeDepTime < getSimTime())) + return; + %cause = ""; + if (%admin) { + messageAll( 'MsgAdminForce', '\c2The Admin removed all duplicate deployables in the mission.' ); + Game.removeDepTime = getSimTime() + delDupPieces(0,0,true) + 1000; + %cause = "(admin)"; + } + else { + %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; + if(%totalVotes > 0 && (%game.totalVotesFor / (ClientGroup.getCount() - $HostGameBotCount)) > ($Host::VotePasspercent / 100)) { + messageAll('MsgVotePassed', '\c2Removing all duplicate deployables in the mission by vote.' ); + delDupPieces(0,0,true); + Game.removeDepTime = getSimTime() + delDupPieces(0,0,true) + 1000; + %cause = "(vote)"; + } + else + messageAll('MsgVoteFailed', '\c2The vote to remove all duplicate deployables in the mission did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + } + if(%cause !$= "") + logEcho("remove all duplicate deployables "@%cause); +} + +//------------------------------------------------------------------------------ +function DefaultGame::VoteRemoveNonPoweredDeployables( %game, %admin, %client ) { + if (!(Game.removeDepTime < getSimTime())) + return; + %cause = ""; + if (%admin) { + messageAll( 'MsgAdminForce', '\c2The Admin removed all deployables in the mission without power.' ); + Game.removeDepTime = getSimTime() + delNonPoweredPieces(true) + 1000; + %cause = "(admin)"; + } + else { + %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; + if(%totalVotes > 0 && (%game.totalVotesFor / (ClientGroup.getCount() - $HostGameBotCount)) > ($Host::VotePasspercent / 100)) { + messageAll('MsgVotePassed', '\c2Removing all deployables in the mission without power by vote.' ); + delNonPoweredPieces(true); + Game.removeDepTime = getSimTime() + delNonPoweredPieces(true) + 1000; + %cause = "(vote)"; + } + else + messageAll('MsgVoteFailed', '\c2The vote to remove all deployables in the mission without power did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + } + if(%cause !$= "") + logEcho("remove all deployables without power "@%cause); +} + +//------------------------------------------------------------------------------ +function DefaultGame::VoteRemoveOrphanedDeployables( %game, %admin, %client ) { + if (!(Game.removeDepTime < getSimTime())) + return; + %cause = ""; + if (%admin) { + messageAll( 'MsgAdminForce', '\c2The Admin removed all orphaned deployables in the mission.' ); + Game.removeDepTime = getSimTime() + delOrphanedPieces(true) + 1000; + %cause = "(admin)"; + } + else { + %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; + if(%totalVotes > 0 && (%game.totalVotesFor / (ClientGroup.getCount() - $HostGameBotCount)) > ($Host::VotePasspercent / 100)) { + messageAll('MsgVotePassed', '\c2Removing all orphaned deployables in the mission by vote.' ); + delOrphanedPieces(true); + Game.removeDepTime = getSimTime() + delOrphanedPieces(true) + 1000; + %cause = "(vote)"; + } + else + messageAll('MsgVoteFailed', '\c2The vote to remove all orphaned deployables in the mission did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + } + if(%cause !$= "") + logEcho("remove all orphaned deployables "@%cause); +} + +//------------------------------------------------------------------------------ +function DefaultGame::VoteRemoveDeployables( %game, %admin, %client ) { + if (!(Game.removeDepTime < getSimTime())) + return; + %cause = ""; + if (%admin) { + messageAll( 'MsgAdminForce', '\c2The Admin removed all deployables in the mission.' ); + Game.removeDepTime = getSimTime() + unpureDeployables() + 1000; + %cause = "(admin)"; + } + else { + %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; + if(%totalVotes > 0 && (%game.totalVotesFor / (ClientGroup.getCount() - $HostGameBotCount)) > ($Host::VotePasspercent / 100)) { + messageAll('MsgVotePassed', '\c2Removing all deployables in the mission by vote.' ); + unpureDeployables(); + Game.removeDepTime = getSimTime() + unpureDeployables() + 1000; + %cause = "(vote)"; + } + else + messageAll('MsgVoteFailed', '\c2The vote to remove all deployables in the mission did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + } + if(%cause !$= "") + logEcho("remove all deployables "@%cause); +} + +//------------------------------------------------------------------------------ +function DefaultGame::VoteInvincibleArmors(%game, %admin) +{ + %setto = ""; + %cause = ""; + if(%admin) + { + if($Host::InvincibleArmors == 1) + { + messageAll('MsgAdminForce', '\c2The Admin has disabled invincible armors.'); + $Host::InvincibleArmors = 0; + %setto = "disabled"; + } + else + { + messageAll('MsgAdminForce', '\c2The Admin has enabled invincible armors.'); + $Host::InvincibleArmors = 1; + %setto = "enabled"; + } + %cause = "(admin)"; + } + else + { + %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; + if(%totalVotes > 0 && (%game.totalVotesFor / (ClientGroup.getCount() - $HostGameBotCount)) > ($Host::VotePasspercent / 100)) + { + if($Host::InvincibleArmors == 1) + { + messageAll('MsgVotePassed', '\c2Invincible armors was disabled by vote.'); + $Host::InvincibleArmors = 0; + %setto = "disabled"; + } + else + { + messageAll('MsgVotePassed', '\c2Invincible armors was enabled by vote.'); + $Host::InvincibleArmors = 1; + %setto = "enabled"; + } + %cause = "(vote)"; + } + else + { + if($Host::InvincibleArmors == 1) + messageAll('MsgVoteFailed', '\c2Disable invincible armors vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + else + messageAll('MsgVoteFailed', '\c2Enable invincible armors vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + } + } + if(%setto !$= "") + logEcho("invincible armors "@%setto SPC %cause); +} + +//------------------------------------------------------------------------------ +function DefaultGame::VoteInvincibleDeployables(%game, %admin) +{ + %setto = ""; + %cause = ""; + if(%admin) + { + if($Host::InvincibleDeployables == 1) + { + messageAll('MsgAdminForce', '\c2The Admin has disabled invincible deployables.'); + $Host::InvincibleDeployables = 0; + %setto = "disabled"; + } + else + { + messageAll('MsgAdminForce', '\c2The Admin has enabled invincible deployables.'); + $Host::InvincibleDeployables = 1; + %setto = "enabled"; + } + %cause = "(admin)"; + } + else + { + %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; + if(%totalVotes > 0 && (%game.totalVotesFor / (ClientGroup.getCount() - $HostGameBotCount)) > ($Host::VotePasspercent / 100)) + { + if($Host::InvincibleDeployables == 1) + { + messageAll('MsgVotePassed', '\c2Invincible deployables was disabled by vote.'); + $Host::InvincibleDeployables = 0; + %setto = "disabled"; + } + else + { + messageAll('MsgVotePassed', '\c2Invincible deployables was enabled by vote.'); + $Host::InvincibleDeployables = 1; + %setto = "enabled"; + } + %cause = "(vote)"; + } + else + { + if($Host::InvincibleDeployables == 1) + messageAll('MsgVoteFailed', '\c2Disable invincible deployables vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + else + messageAll('MsgVoteFailed', '\c2Enable invincible deployables vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + } + } + if(%setto !$= "") + logEcho("invincible deployables "@%setto SPC %cause); +} + +//------------------------------------------------------------------------------ +function DefaultGame::voteUndergroundMode(%game, %admin) +{ + %setto = ""; + %cause = ""; + if(%admin) + { + if($Host::AllowUnderground == 1) + { + messageAll('MsgAdminForce', '\c2The Admin has disabled Underground mode.'); + $Host::AllowUnderground = 0; + %setto = "disabled"; + } + else + { + messageAll('MsgAdminForce', '\c2The Admin has enabled Underground mode.'); + $Host::AllowUnderground = 1; + %setto = "enabled"; + } + %cause = "(admin)"; + } + else + { + %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; + if(%totalVotes > 0 && (%game.totalVotesFor / (ClientGroup.getCount() - $HostGameBotCount)) > ($Host::VotePasspercent / 100)) + { + if($Host::AllowUnderground == 1) + { + messageAll('MsgVotePassed', '\c2Underground mode was disabled by vote.'); + $Host::AllowUnderground = 0; + %setto = "disabled"; + } + else + { + messageAll('MsgVotePassed', '\c2Underground mode was enabled by vote.'); + $Host::AllowUnderground = 1; + %setto = "enabled"; + } + %cause = "(vote)"; + } + else + { + if($Host::AllowUnderground == 1) + messageAll('MsgVoteFailed', '\c2Disable Underground mode vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + else + messageAll('MsgVoteFailed', '\c2Enable Underground mode vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + } + } + if(%setto !$= "") + logEcho("underground mode "@%setto SPC %cause); +} + +//------------------------------------------------------------------------------ +function DefaultGame::voteHazardMode(%game, %admin) +{ + %setto = ""; + %cause = ""; + if(%admin) + { + if($Host::Hazard::Enabled == 1) + { + messageAll('MsgAdminForce', '\c2The Admin has disabled Hazard mode.'); + hazardOff(); + %setto = "disabled"; + } + else + { + messageAll('MsgAdminForce', '\c2The Admin has enabled Hazard mode.'); + hazardOn(); + %setto = "enabled"; + } + %cause = "(admin)"; + } + else + { + %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; + if(%totalVotes > 0 && (%game.totalVotesFor / (ClientGroup.getCount() - $HostGameBotCount)) > ($Host::VotePasspercent / 100)) + { + if($Host::Hazard::Enabled == 1) + { + messageAll('MsgVotePassed', '\c2Hazard mode was disabled by vote.'); + hazardOff(); + %setto = "disabled"; + } + else + { + messageAll('MsgVotePassed', '\c2Hazard mode was enabled by vote.'); + hazardOn(); + %setto = "enabled"; + } + %cause = "(vote)"; + } + else + { + if($Host::Hazard::Enabled == 1) + messageAll('MsgVoteFailed', '\c2Disable Hazard mode vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + else + messageAll('MsgVoteFailed', '\c2Enable Hazard mode vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + } + } + if(%setto !$= "") + logEcho("hazard mode "@%setto SPC %cause); +} + +//------------------------------------------------------------------------------ +function DefaultGame::voteMTCMode(%game, %admin) +{ + %setto = ""; + %cause = ""; + if(%admin) + { + if($Host::MTC::Enabled == 1) + { + messageAll('MsgAdminForce', '\c2The Admin has disabled MTC mode.'); + stopMTC(); + %setto = "disabled"; + } + else + { + messageAll('MsgAdminForce', '\c2The Admin has enabled MTC mode.'); + startMTC(); + %setto = "enabled"; + } + %cause = "(admin)"; + } + else + { + %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; + if(%totalVotes > 0 && (%game.totalVotesFor / (ClientGroup.getCount() - $HostGameBotCount)) > ($Host::VotePasspercent / 100)) + { + if($Host::MTC::Enabled == 1) + { + messageAll('MsgVotePassed', '\c2MTC mode was disabled by vote.'); + stopMTC(); + %setto = "disabled"; + } + else + { + messageAll('MsgVotePassed', '\c2MTC mode was enabled by vote.'); + startMTC(); + %setto = "enabled"; + } + %cause = "(vote)"; + } + else + { + if($Host::MTC::Enabled == 1) + messageAll('MsgVoteFailed', '\c2Disable MTC mode vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + else + messageAll('MsgVoteFailed', '\c2Enable MTC mode vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + } + } + if(%setto !$= "") + logEcho("MTC mode "@%setto SPC %cause); +} + +//------------------------------------------------------------------------------ +function DefaultGame::votePrison(%game, %admin) +{ + %setto = ""; + %cause = ""; + if(%admin) + { + if($Host::Prison::Enabled == 1) + { + messageAll('MsgAdminForce', '\c2The Admin has disabled the prison.'); + prisonDisable(); + %setto = "disabled"; + } + else + { + messageAll('MsgAdminForce', '\c2The Admin has enabled the prison.'); + prisonEnable(); + %setto = "enabled"; + } + %cause = "(admin)"; + } + else + { + %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; + if(%totalVotes > 0 && (%game.totalVotesFor / (ClientGroup.getCount() - $HostGameBotCount)) > ($Host::VotePasspercent / 100)) + { + if($Host::Prison::Enabled == 1) + { + messageAll('MsgVotePassed', '\c2The prison was disabled by vote.'); + prisonDisable(); + %setto = "disabled"; + } + else + { + messageAll('MsgVotePassed', '\c2The prison was enabled by vote.'); + prisonEnable(); + %setto = "enabled"; + } + %cause = "(vote)"; + } + else + { + if($Host::Prison::Enabled == 1) + messageAll('MsgVoteFailed', '\c2Disable prison vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + else + messageAll('MsgVoteFailed', '\c2Enable prison vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + } + } + if(%setto !$= "") + logEcho("prison "@%setto SPC %cause); +} + +//------------------------------------------------------------------------------ +function DefaultGame::VotePrisonKilling(%game, %admin) +{ + %setto = ""; + %cause = ""; + if(%admin) + { + if($Host::Prison::Kill == 1) + { + messageAll('MsgAdminForce', '\c2The Admin has disabled jailing of killers.'); + $Host::Prison::Kill = 0; + %setto = "disabled"; + } + else + { + messageAll('MsgAdminForce', '\c2The Admin has enabled jailing of killers.'); + $Host::Prison::Kill = 1; + %setto = "enabled"; + } + %cause = "(admin)"; + } + else + { + %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; + if(%totalVotes > 0 && (%game.totalVotesFor / (ClientGroup.getCount() - $HostGameBotCount)) > ($Host::VotePasspercent / 100)) + { + if($Host::Prison::Kill == 1) + { + messageAll('MsgVotePassed', '\c2Jailing of killers was disabled by vote.'); + $Host::Prison::Kill = 0; + %setto = "disabled"; + } + else + { + messageAll('MsgVotePassed', '\c2Jailing of killers was enabled by vote.'); + $Host::Prison::Kill = 1; + %setto = "enabled"; + } + %cause = "(vote)"; + } + else + { + if($Host::Prison::Kill == 1) + messageAll('MsgVoteFailed', '\c2Disable jailing of killers vote not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + else + messageAll('MsgVoteFailed', '\c2Enable jailing of killers vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + } + } + if(%setto !$= "") + logEcho("prison killing "@%setto SPC %cause); +} + +//------------------------------------------------------------------------------ +function DefaultGame::VotePrisonTeamKilling(%game, %admin) +{ + %setto = ""; + %cause = ""; + if(%admin) + { + if($Host::Prison::TeamKill == 1) + { + messageAll('MsgAdminForce', '\c2The Admin has disabled jailing of team killers.'); + $Host::Prison::TeamKill = 0; + %setto = "disabled"; + } + else + { + messageAll('MsgAdminForce', '\c2The Admin has enabled jailing of team killers.'); + $Host::Prison::TeamKill = 1; + %setto = "enabled"; + } + %cause = "(admin)"; + } + else + { + %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; + if(%totalVotes > 0 && (%game.totalVotesFor / (ClientGroup.getCount() - $HostGameBotCount)) > ($Host::VotePasspercent / 100)) + { + if($Host::Prison::TeamKill == 1) + { + messageAll('MsgVotePassed', '\c2Jailing of team killers was disabled by vote.'); + $Host::Prison::TeamKill = 0; + %setto = "disabled"; + } + else + { + messageAll('MsgVotePassed', '\c2Jailing of team killers was enabled by vote.'); + $Host::Prison::TeamKill = 1; + %setto = "enabled"; + } + %cause = "(vote)"; + } + else + { + if($Host::Prison::TeamKill == 1) + messageAll('MsgVoteFailed', '\c2Disable jailing of team killers vote not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + else + messageAll('MsgVoteFailed', '\c2Enable jailing of team killers vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + } + } + if(%setto !$= "") + logEcho("prison team killers "@%setto SPC %cause); +} + +//------------------------------------------------------------------------------ +function DefaultGame::VotePrisonDeploySpam(%game, %admin) +{ + %setto = ""; + %cause = ""; + if(%admin) + { + if($Host::Prison::DeploySpam == 1) + { + messageAll('MsgAdminForce', '\c2The Admin has disabled jailing of deploy spammers.'); + $Host::Prison::DeploySpam = 0; + %setto = "disabled"; + } + else + { + messageAll('MsgAdminForce', '\c2The Admin has enabled jailing of deploy spammers.'); + $Host::Prison::DeploySpam = 1; + %setto = "enabled"; + } + %cause = "(admin)"; + } + else + { + %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; + if(%totalVotes > 0 && (%game.totalVotesFor / (ClientGroup.getCount() - $HostGameBotCount)) > ($Host::VotePasspercent / 100)) + { + if($Host::Prison::DeploySpam == 1) + { + messageAll('MsgVotePassed', '\c2Jailing of deploy spammers was disabled by vote.'); + $Host::Prison::DeploySpam = 0; + %setto = "disabled"; + } + else + { + messageAll('MsgVotePassed', '\c2Jailing of deploy spammers was enabled by vote.'); + $Host::Prison::DeploySpam = 1; + %setto = "enabled"; + } + %cause = "(vote)"; + } + else + { + if($Host::Prison::DeploySpam == 1) + messageAll('MsgVoteFailed', '\c2Disable jailing of deploy spammers vote not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + else + messageAll('MsgVoteFailed', '\c2Enable jailing of deploy spammers vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + } + } + if(%setto !$= "") + logEcho("prison deploy spammers "@%setto SPC %cause); +} + +//------------------------------------------------------------------------------ +function DefaultGame::voteNerfWeapons(%game, %admin) +{ + %setto = ""; + %cause = ""; + if(%admin) + { + if($Host::Nerf::Enabled == 1) + { + messageAll('MsgAdminForce', '\c2The Admin has disabled nerf weapons.'); + nerfDisable(); + %setto = "disabled"; + } + else + { + messageAll('MsgAdminForce', '\c2The Admin has enabled nerf weapons.'); + nerfEnable(); + %setto = "enabled"; + } + %cause = "(admin)"; + } + else + { + %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; + if(%totalVotes > 0 && (%game.totalVotesFor / (ClientGroup.getCount() - $HostGameBotCount)) > ($Host::VotePasspercent / 100)) + { + if($Host::Nerf::Enabled == 1) + { + messageAll('MsgVotePassed', '\c2Nerf weapons were disabled by vote.'); + nerfDisable(); + %setto = "disabled"; + } + else + { + messageAll('MsgVotePassed', '\c2Nerf weapons were enabled by vote.'); + nerfEnable(); + %setto = "enabled"; + } + %cause = "(vote)"; + } + else + { + if($Host::Nerf::Enabled == 1) + messageAll('MsgVoteFailed', '\c2Disable nerf weapons vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + else + messageAll('MsgVoteFailed', '\c2Enable nerf weapons vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + } + } + if(%setto !$= "") + logEcho("nerf weapons "@%setto SPC %cause); +} + +//------------------------------------------------------------------------------ +function DefaultGame::voteNerfDance(%game, %admin) +{ + %setto = ""; + %cause = ""; + if(%admin) + { + if($Host::Nerf::DanceAnim == 1 && $Host::Nerf::DeathAnim == 0) + { + messageAll('MsgAdminForce', '\c2The Admin has disabled Nerf Dance mode.'); + $Host::Nerf::DanceAnim = 0; + %setto = "disabled"; + } + else + { + messageAll('MsgAdminForce', '\c2The Admin has enabled Nerf Dance mode.'); + $Host::Nerf::DanceAnim = 1; + $Host::Nerf::DeathAnim = 0; + %setto = "enabled"; + } + %cause = "(admin)"; + } + else + { + %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; + if(%totalVotes > 0 && (%game.totalVotesFor / (ClientGroup.getCount() - $HostGameBotCount)) > ($Host::VotePasspercent / 100)) + { + if($Host::Nerf::DanceAnim == 1 && $Host::Nerf::DeathAnim == 0) + { + messageAll('MsgVotePassed', '\c2Nerf Dance mode was disabled by vote.'); + $Host::Nerf::DanceAnim = 0; + %setto = "disabled"; + } + else + { + messageAll('MsgVotePassed', '\c2Nerf Dance mode was enabled by vote.'); + $Host::Nerf::DanceAnim = 1; + $Host::Nerf::DeathAnim = 0; + %setto = "enabled"; + } + %cause = "(vote)"; + } + else + { + if($Host::Nerf::DanceAnim == 1 && $Host::Nerf::DeathAnim == 0) + messageAll('MsgVoteFailed', '\c2Disable Nerf Dance mode vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + else + messageAll('MsgVoteFailed', '\c2Enable Nerf Dance mode vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + } + } + if(%setto !$= "") + logEcho("nerf dance mode "@%setto SPC %cause); +} + +//------------------------------------------------------------------------------ +function DefaultGame::voteNerfDeath(%game, %admin) +{ + %setto = ""; + %cause = ""; + if(%admin) + { + if($Host::Nerf::DeathAnim == 1) + { + messageAll('MsgAdminForce', '\c2The Admin has disabled Nerf Death mode.'); + $Host::Nerf::DeathAnim = 0; + %setto = "disabled"; + } + else + { + messageAll('MsgAdminForce', '\c2The Admin has enabled Nerf Death mode.'); + $Host::Nerf::DanceAnim = 0; + $Host::Nerf::DeathAnim = 1; + %setto = "enabled"; + } + %cause = "(admin)"; + } + else + { + %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; + if(%totalVotes > 0 && (%game.totalVotesFor / (ClientGroup.getCount() - $HostGameBotCount)) > ($Host::VotePasspercent / 100)) + { + if($Host::Nerf::DeathAnim == 1) + { + messageAll('MsgVotePassed', '\c2Nerf Death mode was disabled by vote.'); + $Host::Nerf::DeathAnim = 0; + %setto = "disabled"; + } + else + { + messageAll('MsgVotePassed', '\c2Nerf Death mode was enabled by vote.'); + $Host::Nerf::DeathAnim = 1; + %setto = "enabled"; + } + %cause = "(vote)"; + } + else + { + if($Host::Nerf::DeathAnim == 1 && $Host::Nerf::DeathAnim == 0) + messageAll('MsgVoteFailed', '\c2Disable Nerf Death mode vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + else + messageAll('MsgVoteFailed', '\c2Enable Nerf Death mode vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + } + } + if(%setto !$= "") + logEcho("nerf death mode "@%setto SPC %cause); +} + +//------------------------------------------------------------------------------ +function DefaultGame::voteNerfPrison(%game, %admin) +{ + %setto = ""; + %cause = ""; + if(%admin) + { + if($Host::Nerf::Prison == 1) + { + messageAll('MsgAdminForce', '\c2The Admin has disabled Nerf Prison mode.'); + $Host::Nerf::Prison = 0; + %setto = "disabled"; + } + else + { + messageAll('MsgAdminForce', '\c2The Admin has enabled Nerf Prison mode.'); + $Host::Nerf::Prison = 1; + %setto = "enabled"; + } + %cause = "(admin)"; + } + else + { + %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; + if(%totalVotes > 0 && (%game.totalVotesFor / (ClientGroup.getCount() - $HostGameBotCount)) > ($Host::VotePasspercent / 100)) + { + if($Host::Nerf::Prison == 1) + { + messageAll('MsgVotePassed', '\c2Nerf Prison mode was disabled by vote.'); + $Host::Nerf::Prison = 0; + %setto = "disabled"; + } + else + { + messageAll('MsgVotePassed', '\c2Nerf Prison mode was enabled by vote.'); + $Host::Nerf::Prison = 1; + %setto = "enabled"; + } + %cause = "(vote)"; + } + else + { + if($Host::Nerf::Prison == 1) + messageAll('MsgVoteFailed', '\c2Disable Nerf Prison mode vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + else + messageAll('MsgVoteFailed', '\c2Enable Nerf Prison mode vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + } + } + if(%setto !$= "") + logEcho("nerf prison mode "@%setto SPC %cause); +} + +//------------------------------------------------------------------------------ +function DefaultGame::voteTournamentMode( %game, %admin, %missionDisplayName, %typeDisplayName, %missionId, %missionTypeId ) +{ + %mission = $HostMissionFile[%missionId]; + if ( %mission $= "" ) + { + error( "Invalid mission index passed to DefaultGame::voteTournamentMode!" ); + return; + } + + %missionType = $HostTypeName[%missionTypeId]; + if ( %missionType $= "" ) + { + error( "Invalid mission type id passed to DefaultGame::voteTournamentMode!" ); + return; + } + + %cause = ""; + if (%admin) + { + messageAll( 'MsgAdminForce', '\c2The Admin has switched the server to Tournament mode (%1).', %missionDisplayName ); + setModeTournament( %mission, %missionType ); + %cause = "(admin)"; + } + else + { + %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; + if(%totalVotes > 0 && (%game.totalVotesFor / (ClientGroup.getCount() - $HostGameBotCount)) > ($Host::VotePasspercent / 100)) + { + messageAll('MsgVotePassed', '\c2Server switched to Tournament mode by vote (%1): %2 percent.', %missionDisplayName, mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + setModeTournament( %mission, %missionType ); + %cause = "(vote)"; + } + else + messageAll('MsgVoteFailed', '\c2Tournament mode vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + } + if(%cause !$= "") + logEcho("tournament mode set "@%cause); +} + +//------------------------------------------------------------------------------ +function DefaultGame::voteMatchStart( %game, %admin) +{ + %cause = ""; + %ready = forceTourneyMatchStart(); + if(%admin) + { + if(!%ready) + { + messageClient( %client, 'msgClient', '\c2No players are ready yet.'); + return; + } + else + { + messageAll('msgMissionStart', '\c2The admin has forced the match to start.'); + %cause = "(admin)"; + startTourneyCountdown(); + } + } + else + { + if(!%ready) + { + messageAll( 'msgClient', '\c2Vote passed to start match, but no players are ready yet.'); + return; + } + else + { + %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; + if(%totalVotes > 0 && (%game.totalVotesFor / (ClientGroup.getCount() - $HostGameBotCount)) > ($Host::VotePasspercent / 100)) + { + messageAll('MsgVotePassed', '\c2The match has been started by vote: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + startTourneyCountdown(); + } + else + messageAll('MsgVoteFailed', '\c2Start Match vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + } + } + + if(%cause !$= "") + logEcho("start match "@%cause); +} + +//------------------------------------------------------------------------------ +function DefaultGame::voteFFAMode( %game, %admin, %client ) +{ + %cause = ""; + %name = getTaggedString(%client.name); + + if (%admin) + { + messageAll('MsgAdminForce', '\c2The Admin has switched the server to Free For All mode.', %client); + setModeFFA($CurrentMission, $CurrentMissionType); + %cause = "(admin)"; + } + else + { + %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; + if(%totalVotes > 0 && (%game.totalVotesFor / (ClientGroup.getCount() - $HostGameBotCount)) > ($Host::VotePasspercent / 100)) + { + messageAll('MsgVotePassed', '\c2Server switched to Free For All mode by vote.', %client); + setModeFFA($CurrentMission, $CurrentMissionType); + %cause = "(vote)"; + } + else + messageAll('MsgVoteFailed', '\c2Free For All mode vote did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + } + if(%cause !$= "") + logEcho("free for all set "@%cause); +} + +//------------------------------------------------------------------------------ +function DefaultGame::voteChangeTimeLimit( %game, %admin, %newLimit ) +{ + if( %newLimit == 999 ) + %display = "unlimited"; + else + %display = %newLimit; + + %cause = ""; + if ( %admin ) + { + messageAll( 'MsgAdminForce', '\c2The Admin changed the mission time limit to %1 minutes.', %display ); + $Host::TimeLimit = %newLimit; + %cause = "(admin)"; + } + else + { + %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; + if(%totalVotes > 0 && (%game.totalVotesFor / (ClientGroup.getCount() - $HostGameBotCount)) > ($Host::VotePasspercent / 100)) + { + messageAll('MsgVotePassed', '\c2The mission time limit was set to %1 minutes by vote.', %display); + $Host::TimeLimit = %newLimit; + %cause = "(vote)"; + } + else + messageAll('MsgVoteFailed', '\c2The vote to change the mission time limit did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + } + + //if the time limit was actually changed... + if(%cause !$= "") + { + logEcho("time limit set to "@%display SPC %cause); + + //if the match has been started, reset the end of match countdown + if ($matchStarted) + { + //schedule the end of match countdown + %elapsedTimeMS = getSimTime() - $missionStartTime; + %curTimeLeftMS = ($Host::TimeLimit * 60 * 1000) - %elapsedTimeMS; + error("time limit="@$Host::TimeLimit@", elapsed="@(%elapsedTimeMS / 60000)@", curtimeleftms="@%curTimeLeftMS); + CancelEndCountdown(); + EndCountdown(%curTimeLeftMS); + cancel(%game.timeSync); + %game.checkTimeLimit(true); + } + } +} + +//------------------------------------------------------------------------------ +function DefaultGame::voteResetServer( %game, %admin, %client ) +{ + %cause = ""; + if ( %admin ) + { + messageAll( 'AdminResetServer', '\c2The Admin has reset the server.' ); + resetServerDefaults(); + %cause = "(admin)"; + } + else + { + %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; + if(%totalVotes > 0 && (%game.totalVotesFor / (ClientGroup.getCount() - $HostGameBotCount)) > ($Host::VotePasspercent / 100)) + { + messageAll('MsgVotePassed', '\c2The Server has been reset by vote.' ); + resetServerDefaults(); + %cause = "(vote)"; + } + else + messageAll('MsgVoteFailed', '\c2The vote to reset Server to defaults did not pass: %1 percent.', mFloor(%game.totalVotesFor/(ClientGroup.getCount() - $HostGameBotCount) * 100)); + } + if(%cause !$= "") + logEcho("server reset "@%cause); +} + +//------------------------------------------------------------------------------ +// all team based votes here +function DefaultGame::voteKickPlayer(%game, %admin, %client) +{ + %cause = ""; + + if(%admin) + { + kick(%client, %admin, %client.guid ); + %cause = "(admin)"; + } + else + { + %team = %client.team; + %totalVotes = %game.votesFor[%game.kickTeam] + %game.votesAgainst[%game.kickTeam]; + if(%totalVotes > 0 && (%game.votesFor[%game.kickTeam] / %totalVotes) > ($Host::VotePasspercent / 100)) + { + kick(%client, %admin, %game.kickGuid); + %cause = "(vote)"; + } + else + { + for ( %idx = 0; %idx < ClientGroup.getCount(); %idx++ ) + { + %cl = ClientGroup.getObject( %idx ); + + if (%cl.team == %game.kickTeam && !%cl.isAIControlled()) + messageClient( %cl, 'MsgVoteFailed', '\c2Kick player vote did not pass' ); + } + } + } + + %game.kickTeam = ""; + %game.kickGuid = ""; + %game.kickClientName = ""; + + if(%cause !$= "") + logEcho(%name@" (cl " @ %game.kickClient @ ") kicked " @ %cause); +} + +//------------------------------------------------------------------------------ +function DefaultGame::banPlayer(%game, %admin, %client) +{ + %cause = ""; + %name = %client.nameBase; + if( %admin ) + { + ban( %client, %admin ); + %cause = "(admin)"; + } + + if(%cause !$= "") + logEcho(%name@" (cl "@%client@") banned "@%cause); +} + +//------------------------------------------------------------------------------ +function DefaultGame::voteAdminPlayer(%game, %admin, %client) +{ + %cause = ""; + + if (%admin) + { + messageAll('MsgAdminAdminPlayer', '\c2The Admin made %2 an admin.', %client, %client.name); + %client.isAdmin = 1; + %cause = "(admin)"; + } + else + { + %totalVotes = %game.totalVotesFor + %game.totalVotesAgainst; + if(%totalVotes > 0 && (%game.totalVotesFor / (ClientGroup.getCount() - $HostGameBotCount)) > ($Host::VotePasspercent / 100)) + { + messageAll('MsgAdminPlayer', '\c2%2 was made an admin by vote.', %client, %client.name); + %client.isAdmin = 1; + %cause = "(vote)"; + } + else + messageAll('MsgVoteFailed', '\c2Vote to make %1 an admin did not pass.', %client.name); + } + if(%cause !$= "") + logEcho(%client.nameBase@" (cl "@%client@") made admin "@%cause); +} + +//------------------------------------------------------------------------------ +function DefaultGame::processGameLink(%game, %client, %arg1, %arg2, %arg3, %arg4, %arg5) +{ + //the default behavior when clicking on a game link is to start observing that client + %targetClient = %arg1; + if ((%client.team == 0) && isObject(%targetClient) && (%targetClient.team != 0)) + { + %prevObsClient = %client.observeClient; + + // update the observer list for this client + observerFollowUpdate( %client, %targetClient, %prevObsClient !$= "" ); + + serverCmdObserveClient(%client, %targetClient); + displayObserverHud(%client, %targetClient); + + if (%targetClient != %prevObsClient) + { + messageClient(%targetClient, 'Observer', '\c1%1 is now observing you.', %client.name); + messageClient(%prevObsClient, 'ObserverEnd', '\c1%1 is no longer observing you.', %client.name); + } + } +} + +//------------------------------------------------------------------------------ +$ScoreHudMaxVisible = 19; +function DefaultGame::updateScoreHud(%game, %client, %tag) +{ + if (Game.numTeams > 1) + { + // Send header: + messageClient( %client, 'SetScoreHudHeader', "", '\t%1%2\t%3%4', + %game.getTeamName(1), $TeamScore[1], %game.getTeamName(2), $TeamScore[2] ); + + // Send subheader: + messageClient( %client, 'SetScoreHudSubheader', "", '\tPLAYERS (%1)SCORE\tPLAYERS (%2)SCORE', + $TeamRank[1, count], $TeamRank[2, count] ); + + %index = 0; + while ( true ) + { + if ( %index >= $TeamRank[1, count]+2 && %index >= $TeamRank[2, count]+2 ) + break; + + //get the team1 client info + %team1Client = ""; + %team1ClientScore = ""; + %col1Style = ""; + if ( %index < $TeamRank[1, count] ) + { + %team1Client = $TeamRank[1, %index]; + %team1ClientScore = %team1Client.score $= "" ? 0 : %team1Client.score; + %col1Style = %team1Client == %client ? "" : ""; + %team1playersTotalScore += %team1Client.score; + } + else if( %index == $teamRank[1, count] && $teamRank[1, count] != 0 && !isDemo() && %game.class $= "CTFGame") + { + %team1ClientScore = "--------------"; + } + else if( %index == $teamRank[1, count]+1 && $teamRank[1, count] != 0 && !isDemo() && %game.class $= "CTFGame") + { + %team1ClientScore = %team1playersTotalScore != 0 ? %team1playersTotalScore : 0; + } + //get the team2 client info + %team2Client = ""; + %team2ClientScore = ""; + %col2Style = ""; + if ( %index < $TeamRank[2, count] ) + { + %team2Client = $TeamRank[2, %index]; + %team2ClientScore = %team2Client.score $= "" ? 0 : %team2Client.score; + %col2Style = %team2Client == %client ? "" : ""; + %team2playersTotalScore += %team2Client.score; + } + else if( %index == $teamRank[2, count] && $teamRank[2, count] != 0 && !isDemo() && %game.class $= "CTFGame") + { + %team2ClientScore = "--------------"; + } + else if( %index == $teamRank[2, count]+1 && $teamRank[2, count] != 0 && !isDemo() && %game.class $= "CTFGame") + { + %team2ClientScore = %team2playersTotalScore != 0 ? %team2playersTotalScore : 0; + } + + //if the client is not an observer, send the message + if (%client.team != 0) + { + messageClient( %client, 'SetLineHud', "", %tag, %index, '\t%5%1%2\t%6%3%4', + %team1Client.name, %team1ClientScore, %team2Client.name, %team2ClientScore, %col1Style, %col2Style ); + } + //else for observers, create an anchor around the player name so they can be observed + else + { + messageClient( %client, 'SetLineHud', "", %tag, %index, '\t%5%1%2\t%6%3%4', + %team1Client.name, %team1ClientScore, %team2Client.name, %team2ClientScore, %col1Style, %col2Style, %team1Client, %team2Client ); + } + + %index++; + } + } + else + { + //tricky stuff here... use two columns if we have more than 15 clients... + %numClients = $TeamRank[0, count]; + if ( %numClients > $ScoreHudMaxVisible ) + %numColumns = 2; + + // Clear header: + messageClient( %client, 'SetScoreHudHeader', "", "" ); + + // Send header: + if (%numColumns == 2) + messageClient(%client, 'SetScoreHudSubheader', "", '\tPLAYERSCORE\tPLAYERSCORE'); + else + messageClient(%client, 'SetScoreHudSubheader', "", '\tPLAYERSCORE'); + + %countMax = %numClients; + if ( %countMax > ( 2 * $ScoreHudMaxVisible ) ) + { + if ( %countMax & 1 ) + %countMax++; + %countMax = %countMax / 2; + } + else if ( %countMax > $ScoreHudMaxVisible ) + %countMax = $ScoreHudMaxVisible; + + for ( %index = 0; %index < %countMax; %index++ ) + { + //get the client info + %col1Client = $TeamRank[0, %index]; + %col1ClientScore = %col1Client.score $= "" ? 0 : %col1Client.score; + %col1Style = %col1Client == %client ? "" : ""; + + //see if we have two columns + if ( %numColumns == 2 ) + { + %col2Client = ""; + %col2ClientScore = ""; + %col2Style = ""; + + //get the column 2 client info + %col2Index = %index + %countMax; + if ( %col2Index < %numClients ) + { + %col2Client = $TeamRank[0, %col2Index]; + %col2ClientScore = %col2Client.score $= "" ? 0 : %col2Client.score; + %col2Style = %col2Client == %client ? "" : ""; + } + } + + //if the client is not an observer, send the message + if (%client.team != 0) + { + if ( %numColumns == 2 ) + messageClient(%client, 'SetLineHud', "", %tag, %index, '\t%5%1%2\t%6%3%4', + %col1Client.name, %col1ClientScore, %col2Client.name, %col2ClientScore, %col1Style, %col2Style ); + else + messageClient( %client, 'SetLineHud', "", %tag, %index, '\t%3%1%2', + %col1Client.name, %col1ClientScore, %col1Style ); + } + //else for observers, create an anchor around the player name so they can be observed + else + { + if ( %numColumns == 2 ) + messageClient(%client, 'SetLineHud', "", %tag, %index, '\t%5%1%2\t%6%3%4', + %col1Client.name, %col1ClientScore, %col2Client.name, %col2ClientScore, %col1Style, %col2Style, %col1Client, %col2Client ); + else + messageClient( %client, 'SetLineHud', "", %tag, %index, '\t%3%1%2', + %col1Client.name, %col1ClientScore, %col1Style, %col1Client ); + } + } + + } + + // Tack on the list of observers: + %observerCount = 0; + for (%i = 0; %i < ClientGroup.getCount(); %i++) + { + %cl = ClientGroup.getObject(%i); + if (%cl.team == 0) + %observerCount++; + } + + if (%observerCount > 0) + { + messageClient( %client, 'SetLineHud', "", %tag, %index, ""); + %index++; + messageClient(%client, 'SetLineHud', "", %tag, %index, '\tOBSERVERS (%1)TIME', %observerCount); + %index++; + for (%i = 0; %i < ClientGroup.getCount(); %i++) + { + %cl = ClientGroup.getObject(%i); + //if this is an observer + if (%cl.team == 0) + { + %obsTime = getSimTime() - %cl.observerStartTime; + %obsTimeStr = %game.formatTime(%obsTime, false); + messageClient( %client, 'SetLineHud', "", %tag, %index, '\t%1%2', + %cl.name, %obsTimeStr ); + %index++; + } + } + } + + //clear the rest of Hud so we don't get old lines hanging around... + messageClient( %client, 'ClearHud', "", %tag, %index ); +} + +//------------------------------------------------------------------------------ +function UpdateClientTimes(%time) +{ + %secondsLeft = %time / 1000; + messageAll('MsgSystemClock', "", (%secondsLeft / 60), %time); +} + +//------------------------------------------------------------------------------ +function notifyMatchStart(%time) +{ + %seconds = mFloor(%time / 1000); + if (%seconds > 2) + MessageAll('MsgMissionStart', '\c2Match starts in %1 seconds.~wfx/misc/hunters_%1.wav', %seconds); + else if (%seconds == 2) + MessageAll('MsgMissionStart', '\c2Match starts in 2 seconds.~wvoice/announcer/ann.match_begins.wav'); + else if (%seconds == 1) + MessageAll('MsgMissionStart', '\c2Match starts in 1 second.'); + UpdateClientTimes(%time); +} + +//------------------------------------------------------------------------------ +function notifyMatchEnd(%time) +{ + %seconds = mFloor(%time / 1000); + if (%seconds > 1) + MessageAll('MsgMissionEnd', '\c2Match ends in %1 seconds.~wfx/misc/hunters_%1.wav', %seconds); + else if (%seconds == 1) + MessageAll('MsgMissionEnd', '\c2Match ends in 1 second.~wfx/misc/hunters_1.wav'); + UpdateClientTimes(%time); +} + +function DefaultGame::formatTime(%game, %tStr, %includeHundredths) +{ + %timeInSeconds = %tStr / 1000; + %mins = mFloor(%timeInSeconds / 60); + if(%mins < 1) + %timeString = "00:"; + else if(%mins < 10) + %timeString = "0" @ %mins @ ":"; + else + %timeString = %mins @ ":"; + + %timeInSeconds -= (%mins * 60); + %secs = mFloor(%timeInSeconds); + if(%secs < 1) + %timeString = %timeString @ "00"; + else if(%secs < 10) + %timeString = %timeString @ "0" @ %secs; + else + %timeString = %timeString @ %secs; + + if (%includeHundredths) + { + %timeString = %timeString @ "."; + %timeInSeconds -= %secs; + %hSecs = mFloor(%timeInSeconds * 100); // will be between 0 and 999 + if(%hSecs < 1) + %timeString = %timeString @ "00"; + else if(%hSecs < 10) + %timeString = %timeString @ "0" @ %hSecs; + else + %timeString = %timeString @ %hSecs; + } + + return %timeString; +} + +//------------------------------------------------------------------------------ +//AI FUNCTIONS +function DefaultGame::AIChooseGameObjective(%game, %client) +{ + AIChooseObjective(%client); +} + +//------------------------------------------------------------------------------ +function DefaultGame::getServerStatusString(%game) +{ + %status = %game.numTeams; + for ( %team = 1; %team - 1 < %game.numTeams; %team++ ) + { + %score = isObject( $teamScore[%team] ) ? $teamScore[%team] : 0; + %teamStr = getTaggedString( %game.getTeamName(%team) ) TAB %score; + %status = %status NL %teamStr; + } + + %status = %status NL ClientGroup.getCount(); + for ( %i = 0; %i < ClientGroup.getCount(); %i++ ) + { + %cl = ClientGroup.getObject( %i ); + %score = %cl.score $= "" ? 0 : %cl.score; + %playerStr = getTaggedString( %cl.name ) TAB getTaggedString( %game.getTeamName(%cl.team) ) TAB %score; + %status = %status NL %playerStr; + } + return( %status ); +} + +//------------------------------------------------------------------------------ +function DefaultGame::OptionsDlgSleep( %game ) +{ + // ignore in the default game... +} + +//------------------------------------------------------------------------------ +function DefaultGame::endMission( %game ) +{ +} diff --git a/scripts/deployables.cs b/scripts/deployables.cs new file mode 100644 index 0000000..42c6146 --- /dev/null +++ b/scripts/deployables.cs @@ -0,0 +1,2075 @@ + + +// deployable objects script +// +// remote pulse sensor, remote motion sensor, remote turrets (indoor +// and outdoor), remote inventory station, remote ammo station +// Note: cameras are treated as grenades, not "regular" deployables + +$Host::CRCTextures = 0; +$TurretIndoorSpaceRadius = 20; // deployed turrets must be this many meters apart +$InventorySpaceRadius = 20; // deployed inventory must be this many meters apart +$TurretIndoorSphereRadius = 50; // radius for turret frequency check +$TurretIndoorMaxPerSphere = 4; // # of turrets allowed in above radius + +$TurretOutdoorSpaceRadius = 25; // deployed turrets must be this many meters apart +$TurretOutdoorSphereRadius = 60; // radius for turret frequency check +$TurretOutdoorMaxPerSphere = 4; // # of turrets allowed in above radius + +$TeamDeployableMax[InventoryDeployable] = 5; +$TeamDeployableMax[TurretIndoorDeployable] = 10; +$TeamDeployableMax[TurretOutdoorDeployable] = 10; +$TeamDeployableMax[PulseSensorDeployable] = 15; +$TeamDeployableMax[MotionSensorDeployable] = 15; + +$TeamDeployableMax[LargeInventoryDeployable] = 10; +$TeamDeployableMax[GeneratorDeployable] = 5; +$TeamDeployableMax[SolarPanelDeployable] = 15; +$TeamDeployableMax[SwitchDeployable] = 10; +$TeamDeployableMax[MediumSensorDeployable] = 4; +$TeamDeployableMax[LargeSensorDeployable] = 2; +$TeamDeployableMax[WallDeployable] = 1000; +$TeamDeployableMax[FloorDeployable] = 1000; +$TeamDeployableMax[wWallDeployable] = 1000; +$TeamDeployableMax[SpineDeployable] = 1000; +$TeamDeployableMax[mSpineDeployable] = 1000; +$TeamDeployableMax[JumpadDeployable] = 50; +$TeamDeployableMax[EscapePodDeployable] = 5; +$TeamDeployableMax[EnergizerDeployable] = 50; +$TeamDeployableMax[TreeDeployable] = 50; +$TeamDeployableMax[CrateDeployable] = 250; +$TeamDeployableMax[DecorationDeployable] = 100; +$TeamDeployableMax[LogoProjectorDeployable] = 10; +$TeamDeployableMax[LightDeployable] = 50; +$TeamDeployableMax[TripwireDeployable] = 50; +$TeamDeployableMax[ForceFieldDeployable] = 100; +$TeamDeployableMax[GravityFieldDeployable] = 30; +$TeamDeployableMax[TelePadPack] = 50; +$TeamDeployableMax[DoorDeployable] = 1000; + +$TeamDeployableMax[TurretBasePack] = 8; +$TeamDeployableMax[TurretLaserDeployable] = 10; +$TeamDeployableMax[DiscTurretDeployable] = 10; +$TeamDeployableMax[TurretMissileRackDeployable] = 10; + +//This could also be in "pack".cs but what the heck +//[most] +$TeamDeployableMax[TurretMpm_Anti_Deployable] = 40; +$TeamDeployableMax[VehiclePadPack] = 40; +$TeamDeployableMax[EmitterDepPack] = 50; +$TeamDeployableMax[AudioDepPack] = 50; +$TeamDeployableMax[DispenserDepPack] = 50; +$TeamDeployableMax[MPM_BeaconPack] = 50; +$TeamDeployableMax[DetonationDepPack] = 5; +//noone cares +$TeamDeployableMax[MpmFuelPack] = 1; +$TeamDeployableMax[MpmAmmoPack] = 1; + +//[most] + +$TeamDeployableMin[TurretIndoorDeployable] = 4; +$TeamDeployableMin[TurretOutdoorDeployable] = 4; +$TeamDeployableMin[TurretBasePack] = 4; +$TeamDeployableMin[TurretLaserDeployable] = 5; +$TeamDeployableMin[DiscTurretDeployable] = 4; +$TeamDeployableMin[TurretMissileRackDeployable] = 4; + +//[most] +$TeamDeployableMin[TurretMpm_Anti_Deployable] = 40; +$TeamDeployableMin[VehiclePadPack] = 40; +$TeamDeployableMin[EmitterDepPack] = 50; +$TeamDeployableMin[AudioDepPack] = 50; +$TeamDeployableMin[DispenserDepPack] = 50; +$TeamDeployableMin[MPM_BeaconPack] = 50; +$TeamDeployableMin[DetonationDepPack] = 5; +//noone cares +$TeamDeployableMin[MpmFuelPack] = 1; +$TeamDeployableMin[MpmAmmoPack] = 1; + +//[most] + +$NotDeployableReason::None = 0; +$NotDeployableReason::MaxDeployed = 1; +$NotDeployableReason::NoSurfaceFound = 2; +$NotDeployableReason::SlopeTooGreat = 3; +$NotDeployableReason::SelfTooClose = 4; +$NotDeployableReason::ObjectTooClose = 5; +$NotDeployableReason::NoTerrainFound = 6; +$NotDeployableReason::NoInteriorFound = 7; +$NotDeployableReason::TurretTooClose = 8; +$NotDeployableReason::TurretSaturation = 9; +$NotDeployableReason::SurfaceTooNarrow = 10; +$NotDeployableReason::InventoryTooClose = 11; + +$MinDeployableDistance = 2.5; +$MaxDeployableDistance = 5.0; //meters from body + +// -------------------------------------------- +// effect datablocks +// -------------------------------------------- + +datablock EffectProfile(TurretDeployEffect) +{ + effectname = "packs/generic_deploy"; + minDistance = 2.5; + maxDistance = 5.0; +}; + +datablock EffectProfile(SensorDeployEffect) +{ + effectname = "powered/sensor_activate"; + minDistance = 2.5; + maxDistance = 5.0; +}; + +datablock EffectProfile(MotionSensorDeployEffect) +{ + effectname = "powered/motion_sensor_activate"; + minDistance = 2.5; + maxDistance = 5.0; +}; + +datablock EffectProfile(StationDeployEffect) +{ + effectname = "packs/inventory_deploy"; + minDistance = 2.5; + maxDistance = 5.0; +}; + +// -------------------------------------------- +// sound datablocks +// -------------------------------------------- + +datablock AudioProfile(TurretDeploySound) +{ + fileName = "fx/packs/turret_place.wav"; + description = AudioClose3d; + preload = true; + effect = TurretDeployEffect; +}; + +datablock AudioProfile(DSound) +{ + filename = "fx/weapons/plasma_rifle_activate.wav"; + //filename = "fx/packs/repair_use.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(SensorDeploySound) +{ + fileName = "fx/powered/sensor_activate.wav"; + description = AudioClose3d; + preload = true; + effect = SensorDeployEffect; + // z0dd - ZOD - Durt, 6/24/02. Eh? This shouldn't be in here. + //effect = MotionSensorDeployEffect; +}; + +datablock AudioProfile(MotionSensorDeploySound) +{ + fileName = "fx/powered/motion_sensor_activate.wav"; + description = AudioClose3d; + preload = true; + // z0dd - ZOD - Durt, 6/24/02. This should be in here. + effect = MotionSensorDeployEffect; +}; + +datablock AudioProfile(StationDeploySound) +{ + fileName = "fx/packs/inventory_deploy.wav"; + description = AudioClose3d; + preload = true; + effect = StationDeployEffect; +}; + +// -------------------------------------------- +// deployable debris definition + +datablock DebrisData( DeployableDebris ) +{ + explodeOnMaxBounce = true; + + elasticity = 0.40; + friction = 0.5; + + lifetime = 200.0; + lifetimeVariance = 5.0; + + minSpinSpeed = 60; + maxSpinSpeed = 600; + + numBounces = 10; + bounceVariance = 1; + + staticOnMaxBounce = true; + + useRadiusMass = true; + baseRadius = 20; + + velocity = 5.0; + velocityVariance = 2.5; + +}; + + +// -------------------------------------------- +// deployable inventory station + +datablock StaticShapeData(DeployedStationInventory) : StaticShapeDamageProfile +{ + className = Station; + shapeFile = "deploy_inventory.dts"; + maxDamage = 0.70; + destroyedLevel = 0.70; + disabledLevel = 0.42; + explosion = DeployablesExplosion; + expDmgRadius = 8.0; + expDamage = 0.35; + expImpulse = 500.0; + + dynamicType = $TypeMasks::StationObjectType; + isShielded = true; + energyPerDamagePoint = 110; + maxEnergy = 50; + rechargeRate = 0.20; + renderWhenDestroyed = false; + doesRepair = true; + + deployedObject = true; + + cmdCategory = "DSupport"; + cmdIcon = CMDStationIcon; + cmdMiniIconName = "commander/MiniIcons/com_inventory_grey"; + targetNameTag = 'Deployable'; + targetTypeTag = 'Station'; + + debrisShapeName = "debris_generic_small.dts"; + debris = DeployableDebris; + heatSignature = 0; +}; + +datablock ShapeBaseImageData(InventoryDeployableImage) +{ + mass = 15; + emap = true; + + shapeFile = "pack_deploy_inventory.dts"; + item = InventoryDeployable; + mountPoint = 1; + offset = "0 0 0"; + deployed = DeployedStationInventory; + heatSignature = 0; + + stateName[0] = "Idle"; + stateTransitionOnTriggerDown[0] = "Activate"; + + stateName[1] = "Activate"; + stateScript[1] = "onActivate"; + stateTransitionOnTriggerUp[1] = "Idle"; + + isLarge = true; + maxDepSlope = 30; + deploySound = StationDeploySound; + + flatMinDeployDis = 1.0; + flatMaxDeployDis = 5.0; + + minDeployDis = 2.5; + maxDeployDis = 5.0; +}; + +datablock ItemData(InventoryDeployable) +{ + className = Pack; + catagory = "Deployables"; + shapeFile = "pack_deploy_inventory.dts"; + mass = 3.0; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 1; + rotate = false; + image = "InventoryDeployableImage"; + pickUpName = "an inventory pack"; + heatSignature = 0; + + computeCRC = true; + emap = true; + +}; + +// -------------------------------------------- +// deployable motion sensor + +datablock SensorData(DeployMotionSensorObj) +{ + detects = true; + detectsUsingLOS = true; + detectsActiveJammed = false; + detectsPassiveJammed = true; + detectsCloaked = true; + detectionPings = false; + detectMinVelocity = 2; + detectRadius = 60; +}; + +datablock StaticShapeData(DeployedMotionSensor) : StaticShapeDamageProfile +{ + className = Sensor; + shapeFile = "deploy_sensor_motion.dts"; + maxDamage = 0.6; + destroyedLevel = 0.6; + disabledLevel = 0.4; + explosion = DeployablesExplosion; + dynamicType = $TypeMasks::SensorObjectType; + + deployedObject = true; + + cmdCategory = "DSupport"; + cmdIcon = CMDSensorIcon; + cmdMiniIconName = "commander/MiniIcons/com_deploymotionsensor"; + targetNameTag = 'Deployable Motion'; + targetTypeTag = 'Sensor'; + sensorData = DeployMotionSensorObj; + sensorRadius = DeployMotionSensorObj.detectRadius; + sensorColor = "9 136 255"; + deployAmbientThread = true; + + debrisShapeName = "debris_generic_small.dts"; + debris = DeployableDebris; + heatSignature = 0; +}; + +datablock ShapeBaseImageData(MotionSensorDeployableImage) +{ + shapeFile = "pack_deploy_sensor_motion.dts"; + item = MotionSensorDeployable; + mountPoint = 1; + offset = "0 0 0"; + deployed = DeployedMotionSensor; + + stateName[0] = "Idle"; + stateTransitionOnTriggerDown[0] = "Activate"; + + stateName[1] = "Activate"; + stateScript[1] = "onActivate"; + stateTransitionOnTriggerUp[1] = "Idle"; + + maxDepSlope = 360; + deploySound = MotionSensorDeploySound; + emap = true; + heatSignature = 1; + + minDeployDis = 0.5; + maxDeployDis = 5.0; //meters from body +}; + +datablock ItemData(MotionSensorDeployable) +{ + className = Pack; + catagory = "Deployables"; + shapeFile = "pack_deploy_sensor_motion.dts"; + mass = 2.0; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 1; + rotate = false; + image = "MotionSensorDeployableImage"; + pickUpName = "a motion sensor pack"; + + computeCRC = true; + emap = true; + heatSignature = 0; + + //maxSensors = 3; + maxSensors = 2; +}; + +// -------------------------------------------- +// deployable pulse sensor + +datablock SensorData(DeployPulseSensorObj) +{ + detects = true; + detectsUsingLOS = true; + detectsPassiveJammed = false; + detectsCloaked = false; + detectionPings = true; + detectRadius = 150; +}; + +datablock StaticShapeData(DeployedPulseSensor) : StaticShapeDamageProfile +{ + className = Sensor; + shapeFile = "deploy_sensor_pulse.dts"; + maxDamage = 0.6; + destroyedLevel = 0.6; + disabledLevel = 0.4; + explosion = DeployablesExplosion; + dynamicType = $TypeMasks::SensorObjectType; + + deployedObject = true; + + cmdCategory = "DSupport"; + cmdIcon = CMDSensorIcon; + cmdMiniIconName = "commander/MiniIcons/com_deploypulsesensor"; + targetNameTag = 'Deployable'; + targetTypeTag = 'Pulse Sensor'; + sensorData = DeployPulseSensorObj; + sensorRadius = DeployPulseSensorObj.detectRadius; + sensorColor = "255 194 9"; + deployAmbientThread = true; + + debrisShapeName = "debris_generic_small.dts"; + debris = DeployableDebris; + heatSignature = 0; +}; + +datablock ShapeBaseImageData(PulseSensorDeployableImage) +{ + shapeFile = "pack_deploy_sensor_pulse.dts"; + item = PulseSensorDeployable; + mountPoint = 1; + offset = "0 0 0"; + deployed = DeployedPulseSensor; + + stateName[0] = "Idle"; + stateTransitionOnTriggerDown[0] = "Activate"; + + stateName[1] = "Activate"; + stateScript[1] = "onActivate"; + stateTransitionOnTriggerUp[1] = "Idle"; + deploySound = SensorDeploySound; + + maxDepSlope = 40; + emap = true; + heatSignature = 0; + + minDeployDis = 0.5; + maxDeployDis = 5.0; //meters from body +}; + +datablock ItemData(PulseSensorDeployable) +{ + className = Pack; + catagory = "Deployables"; + shapeFile = "pack_deploy_sensor_pulse.dts"; + mass = 2.0; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 1; + rotate = false; + image = "PulseSensorDeployableImage"; + pickUpName = "a pulse sensor pack"; + + computeCRC = true; + emap = true; + + maxSensors = 2; +}; + +// -------------------------------------------- +// deployable outdoor turret + +datablock ShapeBaseImageData(TurretOutdoorDeployableImage) +{ + mass = 15; + + shapeFile = "pack_deploy_turreto.dts"; + item = TurretOutdoorDeployable; + mountPoint = 1; + offset = "0 0 0"; + deployed = TurretDeployedOutdoor; + + stateName[0] = "Idle"; + stateTransitionOnTriggerDown[0] = "Activate"; + + stateName[1] = "Activate"; + stateScript[1] = "onActivate"; + stateTransitionOnTriggerUp[1] = "Idle"; + + maxDamage = 4.5; + destroyedLevel = 4.5; + disabledLevel = 4.0; + + isLarge = true; + emap = true; + + maxDepSlope = 40; + deploySound = TurretDeploySound; + + minDeployDis = 0.5; + maxDeployDis = 5.0; //meters from body +}; + +datablock ItemData(TurretOutdoorDeployable) +{ + className = Pack; + catagory = "Deployables"; + shapeFile = "pack_deploy_turreto.dts"; + mass = 3.0; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 1; + rotate = false; + image = "TurretOutdoorDeployableImage"; + pickUpName = "a landspike turret pack"; + + computeCRC = true; + emap = true; + +}; + +// -------------------------------------------- +// deployable indoor turret (3 varieties -- floor, wall and ceiling) + +datablock ShapeBaseImageData(TurretIndoorDeployableImage) +{ + mass = 15; + + shapeFile = "pack_deploy_turreti.dts"; + item = TurretIndoorDeployable; + mountPoint = 1; + offset = "0 0 0"; + + stateName[0] = "Idle"; + stateTransitionOnTriggerDown[0] = "Activate"; + + stateName[1] = "Activate"; + stateScript[1] = "onActivate"; + stateTransitionOnTriggerUp[1] = "Idle"; + + isLarge = true; + emap = true; + + maxDepSlope = 360; + deploySound = TurretDeploySound; + + minDeployDis = 0.5; + maxDeployDis = 5.0; //meters from body +}; + +datablock ItemData(TurretIndoorDeployable) +{ + className = Pack; + catagory = "Deployables"; + shapeFile = "pack_deploy_turreti.dts"; + mass = 3.0; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 1; + rotate = false; + image = "TurretIndoorDeployableImage"; + pickUpName = "a spider clamp turret pack"; + + computeCRC = true; + emap = true; + +}; + +// -------------------------------------------- +// miscellaneous yet handy functions + +function posFromTransform(%transform) +{ + // the first three words of an object's transform are the object's position + %position = getWord(%transform, 0) @ " " @ getWord(%transform, 1) @ " " @ getWord(%transform, 2); + return %position; +} + +function rotFromTransform(%transform) +{ + // the last four words of an object's transform are the object's rotation + %rotation = getWord(%transform, 3) @ " " @ getWord(%transform, 4) @ " " @ getWord(%transform, 5) @ " " @ getWord(%transform, 6); + return %rotation; +} + +function posFromRaycast(%transform) +{ + // the 2nd, 3rd, and 4th words returned from a successful raycast call are the position of the point + %position = getWord(%transform, 1) @ " " @ getWord(%transform, 2) @ " " @ getWord(%transform, 3); + return %position; +} + +function normalFromRaycast(%transform) +{ + // the 5th, 6th and 7th words returned from a successful raycast call are the normal of the surface + %norm = getWord(%transform, 4) @ " " @ getWord(%transform, 5) @ " " @ getWord(%transform, 6); + return %norm; +} + +function addToDeployGroup(%object) +{ + // all deployables should go into a special group for AI purposes + %depGroup = nameToID("MissionCleanup/Deployables"); + if (%depGroup <= 0) { + %depGroup = new SimGroup("Deployables"); + MissionCleanup.add(%depGroup); + } + %depGroup.add(%object); +} + + + +function Deployables::searchView(%obj, %searchRange, %mask) +{ + // get the eye vector and eye transform of the player + %eyeVec = %obj.getEyeVector(); + %eyeTrans = %obj.getEyeTransform(); + + // extract the position of the player's camera from the eye transform (first 3 words) + %eyePos = posFromTransform(%eyeTrans); + + // normalize the eye vector + %nEyeVec = VectorNormalize(%eyeVec); + + // scale (lengthen) the normalized eye vector according to the search range + %scEyeVec = VectorScale(%nEyeVec, %searchRange); + + // add the scaled & normalized eye vector to the position of the camera + %eyeEnd = VectorAdd(%eyePos, %scEyeVec); + +// %pack = %obj.getMountedImage($BackpackSlot); + +//if (%pack.deployed.ClassName $= "mspine") +// { +// %mask2 = $TypeMasks::StaticObjectType; +// %searchResult = containerRayCast(%eyePos, %eyeEnd, %mask2, 0); +// if ((%searchResult) && (%searchResult.getType() & $TypeMasks::StaticObjectType)) +// { +// if (%searchResult.getDataBlock().className $= "mspine") +// return %searchResult; +// else if (%searchResult.getDataBlock().className $= "spine") +// return %searchResult; +// else if (%searchResult.getDataBlock().className $= "Wall") +// return %searchResult; +// else if (%searchResult.getDataBlock().className $= "wWall") +// return %searchResult; +// else if (%searchResult.getDataBlock().className $= "item") +// return %searchResult; +// else if (%searchResult.getDataBlock().className $= "floor") +// return %searchResult; +// %searchResult = ""; +// } +// } + + // see if anything gets hit + %searchResult = containerRayCast(%eyePos, %eyeEnd, %mask, 0); + if (%searchResult) + %pos2 = getWords(%searchResult, 1, 3); + else + %pos2 = %eyeEnd; + %searchResult2 = containerRayCast(%eyePos, %pos2, $TypeMasks::StaticShapeObjectType | $TypeMasks::ForceFieldObjectType, 0); + if (%searchResult2) { + if (%searchResult2.getDataBlock().className $= "wWall") + return %searchResult2; + else if (%searchResult2.getDataBlock().className $= "Wall") + return %searchResult2; + else if (%searchResult2.getDataBlock().className $= "spine") + return %searchResult2; + else if (%searchResult2.getDataBlock().className $= "mspine") + return %searchResult2; + else if (%searchResult2.getDataBlock().className $= "item") + return %searchResult2; + else if (%searchResult2.getDataBlock().className $= "floor") + return %searchResult2; + else if (%searchResult2.getDataBlock().className $= "tree") + return %searchResult2; + else if (%searchResult2.getDataBlock().className $= "crate") + return %searchResult2; + else if (%searchResult2.getDataBlock().className $= "decoration") { + if (%searchResult2.getDataBlock().getName() $= "DeployedDecoration6") + return %searchResult2; + else + return; // Don't deploy on or through other decorations, since there are problems with surface normals + } + else if (%searchResult2.getType() & $TypeMasks::ForceFieldObjectType) + return; // Don't deploy inside or through forcefields + } + return %searchResult; +} + +//-----------------------// +// Deployable Procedures // +//-----------------------// + +//------------------------------------------------- +function ShapeBaseImageData::testMaxDeployed(%item, %plyr) { + if (%item.item $= TurretOutdoorDeployable + || %item.item $= TurretIndoorDeployable + || %item.item $= TurretBasePack + || %item.item $= TurretLaserDeployable + || %item.item $= TurretMissileRackDeployable + || %item.item $= TurretMpm_Anti_Deployable + || %item.item $= DiscTurretDeployable) + %itemCount = countTurretsAllowed(%item.item); + else + %itemCount = $TeamDeployableMax[%item.item]; + + return $TeamDeployedCount[%plyr.team, %item.item] >= %itemCount; +} + +//------------------------------------------------- +function ShapeBaseImageData::testNoSurfaceInRange(%item, %plyr) +{ + return ! Deployables::searchView(%plyr, $MaxDeployDistance, $TypeMasks::TerrainObjectType | $TypeMasks::InteriorObjectType | $TypeMasks::StaticShapeObjectType); +} + +//------------------------------------------------- +function ShapeBaseImageData::testSlopeTooGreat(%item) +{ + if (%item.surface) + { + return getTerrainAngle(%item.surfaceNrm) > %item.maxDepSlope; + } +} + +//------------------------------------------------- +function ShapeBaseImageData::testSelfTooClose(%item, %plyr) +{ + InitContainerRadiusSearch(%item.surfacePt, $MinDeployDistance, $TypeMasks::PlayerObjectType); + + return containerSearchNext() == %plyr; +} + +//------------------------------------------------- +function ShapeBaseImageData::testObjectTooClose(%item) { + %mask = ($TypeMasks::VehicleObjectType | $TypeMasks::MoveableObjectType | + $TypeMasks::StaticShapeObjectType | + $TypeMasks::ForceFieldObjectType | $TypeMasks::ItemObjectType | + $TypeMasks::PlayerObjectType | $TypeMasks::TurretObjectType); + + InitContainerRadiusSearch(%item.surfacePt,$MinDeployDistance,%mask); + + // TODO - update this + while ((%test = containerSearchNext()) != 0) { + %className = %test.getDataBlock().className; + if (vectorDist(%item.surfacePt,%test.getPosition()) < $MinDeployDistance + && %className !$= "Wall" && %className !$= "wWall" && %className !$= "spine" && %className !$= "mspine" + && %className !$= "floor" && %className !$= "tree" && %className !$= "crate" && %className !$= "decoration" + && %className !$= "light" && %className !$= "decontarget" && %className !$= "item" + && %className !$= "pack" ) + return %test; + } + return 0; +} + +//------------------------------------------------- +function TurretOutdoorDeployableImage::testNoTerrainFound(%item) +{ + return %item.surface.getClassName() !$= TerrainBlock; +} + +function ShapeBaseImageData::testNoTerrainFound(%item, %surface) +{ + //don't check this for non-Landspike turret deployables +} + +//------------------------------------------------- +function TurretIndoorDeployableImage::testNoInteriorFound(%item) { + if (%item.surface.getType() & $TypeMasks::StaticShapeObjectType) { + %className = %item.surface.getDataBlock().className; + if (%className $= "Wall") + return 0; + else if (%className $= "wWall") + return 0; + else if (%className $= "spine") + return 0; + else if (%className $= "mspine") + return 0; + else if (%className $= "item") + return 0; + else if (%className $= "floor") + return 0; + else if (%className $= "tree") + return 0; + else if (%className $= "crate") + return 0; + else if (%className $= "decoration") + return 0; + } + return %item.surface.getClassName() !$= InteriorInstance; +} + +function ShapeBaseImageData::testNoInteriorFound(%item, %surface) +{ + //don't check this for non-Clasping turret deployables +} + +//------------------------------------------------- +function TurretIndoorDeployableImage::testHavePurchase(%item, %xform) +{ + %footprintRadius = 0.34; + %collMask = $TypeMasks::InteriorObjectType; + return %item.deployed.checkDeployPurchase(%xform, %footprintRadius, %collMask); +} + +function ShapeBaseImageData::testHavePurchase(%item, %xform) +{ + //don't check this for non-Clasping turret deployables + return true; +} + +//------------------------------------------------- +function ShapeBaseImageData::testInventoryTooClose(%item, %plyr) +{ + return false; +} + +function InventoryDeployableImage::testInventoryTooClose(%item, %plyr) +{ + InitContainerRadiusSearch(%item.surfacePt, $InventorySpaceRadius, $TypeMasks::StaticShapeObjectType); + + // old function was only checking whether the first object found was a turret -- also wasn't checking + // which team the object was on + %turretInRange = false; + while((%found = containerSearchNext()) != 0) + { + %foundName = %found.getDataBlock().getName(); + if ( (%foundName $= DeployedStationInventory) ) + if (%found.team == %plyr.team) + { + %turretInRange = true; + break; + } + } + return %turretInRange; +} + + +// TODO - keep this up to date +function isDeployedTurret(%obj) { + %dataBlockName = %obj.getDataBlock().getName(); + if ((%dataBlockName $= TurretDeployedFloorIndoor) + || (%dataBlockName $= TurretDeployedWallIndoor) + || (%dataBlockName $= TurretDeployedCeilingIndoor) + || (%dataBlockName $= TurretDeployedOutdoor) + || (%dataBlockName $= TurretDeployedBase) + || (%dataBlockName $= LaserDeployed) + || (%dataBlockName $= MissileRackTurretDeployed) + || (%dataBlockName $= Mpm_anti_TurretDeployed) + || (%dataBlockName $= DiscTurretDeployed)) + return 1; + return 0; +} + +// TODO - keep this up to date +function isDeployableTurret(%item) { + if ((%item $= TurretIndoorDeployable) + || (%item $= TurretOutdoorDeployable) + || (%item $= TurretBasePack) + || (%item $= TurretLaserDeployable) + || (%item $= TurretMissileRackDeployable) + || (%item $= TurretMpm_anti_Deployable) + || (%item $= DiscTurretDeployable)) + return 1; + return 0; +} + +function TurretIndoorDeployableImage::testTurretTooClose(%item, %plyr) { + InitContainerRadiusSearch(%item.surfacePt, $TurretIndoorSpaceRadius, $TypeMasks::StaticShapeObjectType); + // old function was only checking whether the first object found was a turret -- also wasn't checking + // which team the object was on + %turretInRange = false; + while((%found = containerSearchNext()) != 0) { + if (isDeployedTurret(%found)) { + if (%found.team == %plyr.team) { + %turretInRange = true; + break; + } + } + } + return %turretInRange; +} + +function TurretOutdoorDeployableImage::testTurretTooClose(%item, %plyr) { + InitContainerRadiusSearch(%item.surfacePt, $TurretOutdoorSpaceRadius, $TypeMasks::StaticShapeObjectType); + // old function was only checking whether the first object found was a turret -- also wasn't checking + // which team the object was on + %turretInRange = false; + while((%found = containerSearchNext()) != 0) { + if (isDeployedTurret(%found)) { + if (%found.team == %plyr.team) { + %turretInRange = true; + break; + } + } + } + return %turretInRange; +} + +function TurretDeployableImage::testTurretTooClose(%item, %plyr) { + return TurretOutdoorDeployableImage::testTurretTooClose(%item, %plyr); +} + +function TurretLaserDeployableImage::testTurretTooClose(%item, %plyr) { + return TurretIndoorDeployableImage::testTurretTooClose(%item, %plyr); +} + +function TurretMissileRackDeployableImage::testTurretTooClose(%item, %plyr) { + return TurretOutdoorDeployableImage::testTurretTooClose(%item, %plyr); +} + + +function TurretMpm_Anti_DeployableImage::testTurretTooClose(%item, %plyr) { + return TurretOutdoorDeployableImage::testTurretTooClose(%item, %plyr); +} + + +function DiscTurretDeployableImage::testTurretTooClose(%item, %plyr) { + return TurretOutdoorDeployableImage::testTurretTooClose(%item, %plyr); +} + +function ShapeBaseImageData::testTurretTooClose(%item, %plyr) +{ + //don't check this for non-turret deployables +} + +//[most] +function ShapeBaseImageData::testSurfaceTooNarrow(%item,%surface) +{ + //don't check this for non-v-pad deployables +} +//[most] + +// TODO - keep this up to date + +//------------------------------------------------- +function TurretIndoorDeployableImage::testTurretSaturation(%item) { + %highestDensity = 0; + InitContainerRadiusSearch(%item.surfacePt, $TurretIndoorSphereRadius, $TypeMasks::StaticShapeObjectType); + %found = containerSearchNext(); + while(%found) { + if (isDeployedTurret(%found)) { + //found one + %numTurretsNearby++; + %nearbyDensity = testNearbyDensity(%found, $TurretIndoorSphereRadius); + if (%nearbyDensity > %highestDensity) + %highestDensity = %nearbyDensity; + } + %found = containerSearchNext(); + } + if (%numTurretsNearby > %highestDensity) + %highestDensity = %numTurretsNearby; + return %highestDensity > $TurretIndoorMaxPerSphere; +} + +function TurretOutdoorDeployableImage::testTurretSaturation(%item) { + %highestDensity = 0; + InitContainerRadiusSearch(%item.surfacePt, $TurretOutdoorSphereRadius, $TypeMasks::StaticShapeObjectType); + %found = containerSearchNext(); + while(%found) { + if (isDeployedTurret(%found)) { + //found one + %numTurretsNearby++; + %nearbyDensity = testNearbyDensity(%found, $TurretOutdoorSphereRadius); + if (%nearbyDensity > %highestDensity) + %highestDensity = %nearbyDensity; + } + %found = containerSearchNext(); + } + if (%numTurretsNearby > %highestDensity) + %highestDensity = %numTurretsNearby; + return %highestDensity > $TurretOutdoorMaxPerSphere; +} + +function TurretDeployableImage::testTurretSaturation(%item, %plyr) { + return TurretOutdoorDeployableImage::testTurretSaturation(%item, %plyr); +} + +function TurretLaserDeployableImage::testTurretSaturation(%item, %plyr) { + return TurretIndoorDeployableImage::testTurretSaturation(%item, %plyr); +} + +function TurretMissileRackDeployableImage::testTurretSaturation(%item, %plyr) { + return TurretOutdoorDeployableImage::testTurretSaturation(%item, %plyr); +} + + +function TurretMpm_Anti_DeployableImage::testTurretSaturation(%item, %plyr) { + return TurretOutdoorDeployableImage::testTurretSaturation(%item, %plyr); +} + +function DiscTurretDeployableImage::testTurretSaturation(%item, %plyr) { + return TurretOutdoorDeployableImage::testTurretSaturation(%item, %plyr); +} + +function ShapeBaseImageData::testTurretSaturation(%item, %surfacePt) +{ + //don't check this for non-turret deployables +} + +function testNearbyDensity(%item, %radius) { + //this checks how many turrets are in adjacent spheres in case placing a new one overloads them. + %surfacePt = posFromTransform(%item.getTransform()); + %turretCount = 0; + InitContainerRadiusSearch(%surfacePt, %radius, $TypeMasks::StaticShapeObjectType); + %found = containerSearchNext(); + while(%found) { + if (isDeployedTurret(%found)) + %turretCount++; + %found = containerSearchNext(); + } + return %turretCount; +} + +//------------------------------------------------- +//if this function, or any of the included tests are changed, those changes need to be reflected in function: +//AIODeployEquipment::weight(%this, %client, %level), found in aiObjectives.cs --tinman + +function ShapeBaseImageData::testInvalidDeployConditions(%item, %plyr, %slot) { + cancel(%plyr.deployCheckThread); + %disqualified = $NotDeployableReason::None; //default + $MaxDeployDistance = %item.maxDeployDis; + $MinDeployDistance = %item.minDeployDis; + + %pack = %plyr.getMountedImage($BackpackSlot); + + if (%pack.deployed.className $= "decoration") { + if (%plyr.packSet == 6) + $MinDeployDistance = 2; + if (%plyr.packSet == 10) + $MinDeployDistance = 5; + if (%plyr.packSet == 11) + $MinDeployDistance = 4; + } + + %surface = Deployables::searchView(%plyr, + $MaxDeployDistance, + ($TypeMasks::TerrainObjectType | + $TypeMasks::InteriorObjectType | + $TypeMasks::StaticShapeObjectType)); + if (%surface) { + %surfacePt = posFromRaycast(%surface); + %surfaceNrm = normalFromRaycast(%surface); + + // Check that point to see if anything is obstructing it... + %eyeTrans = %plyr.getEyeTransform(); + %eyePos = posFromTransform(%eyeTrans); + + %searchResult = containerRayCast(%eyePos, %surfacePt, -1, %plyr); + if (!%searchResult) { + %item.surface = %surface; + %item.surfacePt = %surfacePt; + %item.surfaceNrm = %surfaceNrm; + } + else { + if (checkPositions(%surfacePT, posFromRaycast(%searchResult))) { + %item.surface = %surface; + %item.surfacePt = %surfacePt; + %item.surfaceNrm = %surfaceNrm; + } + else { + // Deploy through water + if (%searchResult.getType() & $TypeMasks::WaterObjectType) { + %item.surface = %surface; + %item.surfacePt = %surfacePt; + %item.surfaceNrm = %surfaceNrm; + } + // Redundant - already checking StaticShape above now (v0.62a) +// // Deploy on StaticShapes +// else if (%searchResult.getType() & $TypeMasks::StaticShapeObjectType) { +// %item.surface = %surface; +// %item.surfacePt = %surfacePt; +// %item.surfaceNrm = %surfaceNrm; +// } + // Don't set the item +// TODO - make a proper $NotDeployableReason for this + else + %disqualified = $NotDeployableReason::MaxDeployed; + } + } + if (!getTerrainAngle(%surfaceNrm) && %item.flatMaxDeployDis !$= "") { + $MaxDeployDistance = %item.flatMaxDeployDis; + $MinDeployDistance = %item.flatMinDeployDis; + } + } + + %item.surfaceinher = 0; + if (%item.surface.needsFit == 1) { + %item.surfaceinher = 1; +// new code + %mask = invFace(%item.surfaceNrm); + %narrower = vectorMultiply(%mask,%item.surface.getRealSize()); + %subject = vectorNormalize(topVec(%narrower)); + %item.surfaceNrm2 = realVec(%item.surface,%subject); +// old code +// if (vAbs(%item.surfaceNrm) $= "0 0 1") +// %item.surfaceNrm2 = realVec(%item.surface,"1 0 0"); +// else +// %item.surfaceNrm2 = realVec(%item.surface,"0 0 1"); + %item.surfaceNrm = VectorNormalize(realVec(%item.surface,%surfaceNrm)); + %item.surfaceNrm2 = VectorNormalize(%item.surfaceNrm2); + %mCenter = "0 0 -0.5"; + %className = %item.surface.getDataBlock().className; + if (%className !$= "tree" && %className !$= "crate" && %className !$= "vpad") + %item.surfacePt = link(%item.surface,%surfaceNrm,%surfacePt,VectorScale(getjoint(%item),0.5),%mCenter); + if (%className $= "decoration") { + if (%item.surface.getDataBlock().getName() $= "DeployedDecoration6") { + %item.surfacePt = vectorAdd(%item.surfacePt,vectorScale(realVec(%item.surface,"0 0 1"),3.3)); + %item.surfaceNrm = realVec(%item.surface,"0 0 1"); + } + } + } + + if (%item.testMaxDeployed(%plyr)) + { + %disqualified = $NotDeployableReason::MaxDeployed; + } + else if (%item.testNoSurfaceInRange(%plyr)) + { + %disqualified = $NotDeployableReason::NoSurfaceFound; + } + else if (%item.testNoTerrainFound(%surface)) + { + %disqualified = $NotDeployableReason::NoTerrainFound; + } + else if (%item.testNoInteriorFound()) + { + %disqualified = $NotDeployableReason::NoInteriorFound; + } + else if (%item.testSurfaceTooNarrow(%surface)) + { + %disqualified = $NotDeployableReason::SurfaceTooNarrow; + } + else if (%item.testSlopeTooGreat(%surface, %surfaceNrm)) + { + %disqualified = $NotDeployableReason::SlopeTooGreat; + } + else if (%item.testSelfTooClose(%plyr, %surfacePt)) + { + %disqualified = $NotDeployableReason::SelfTooClose; + } + else if (%item.testObjectTooClose(%surfacePt,%plyr)) + { + %disqualified = $NotDeployableReason::ObjectTooClose; + } + else if (%item.testTurretTooClose(%plyr) && $Host::Purebuild != 1) + { + %disqualified = $NotDeployableReason::TurretTooClose; + } + else if (%item.testInventoryTooClose(%plyr)) + { + %disqualified = $NotDeployableReason::InventoryTooClose; + } + else if (%item.testTurretSaturation() && $Host::Purebuild != 1) + { + %disqualified = $NotDeployableReason::TurretSaturation; + } + else if (%disqualified == $NotDeployableReason::None) + { + // Test that there are no obstructing objects that this object + // will intersect with + // + %rot = %item.getInitialRotation(%plyr); + if (%item.deployed.className $= "DeployedTurret") + { + %xform = %item.deployed.getDeployTransform(%item.surfacePt, %item.surfaceNrm); + } + else + { + %xform = %surfacePt SPC %rot; + } + } + + if (%plyr.getMountedImage($BackpackSlot) == %item) //player still have the item? + { + if (%disqualified) + activateDeploySensorRed(%plyr); + else + activateDeploySensorGrn(%plyr); + + if (%plyr.client.deployPack == true) { + %item.attemptDeploy(%plyr, %slot, %disqualified); + } + else + { + %plyr.deployCheckThread = %item.schedule(25, "testInvalidDeployConditions", %plyr, %slot); //update checks every 50 milliseconds + } + } + else + deactivateDeploySensor(%plyr); +} + +function checkPositions(%pos1, %pos2) +{ + %passed = true; + if ((mFloor(getWord(%pos1, 0)) - mFloor(getWord(%pos2,0)))) + %passed = false; + if ((mFloor(getWord(%pos1, 1)) - mFloor(getWord(%pos2,1)))) + %passed = false; + if ((mFloor(getWord(%pos1, 2)) - mFloor(getWord(%pos2,2)))) + %passed = false; + return %passed; +} + +function ShapeBaseImageData::attemptDeploy(%item, %plyr, %slot, %disqualified) +{ + deactivateDeploySensor(%plyr); + Deployables::displayErrorMsg(%item, %plyr, %slot, %disqualified); +} + +function activateDeploySensorRed(%pl) +{ + if (%pl.deploySensor !$= "red") + { + messageClient(%pl.client, 'msgDeploySensorRed', ""); + %pl.deploySensor = "red"; + } +} + +function activateDeploySensorGrn(%pl) +{ + if (%pl.deploySensor !$= "green") + { + messageClient(%pl.client, 'msgDeploySensorGrn', ""); + %pl.deploySensor = "green"; + } +} + +function deactivateDeploySensor(%pl) +{ + if (%pl.deploySensor !$= "") + { + messageClient(%pl.client, 'msgDeploySensorOff', ""); + %pl.deploySensor = ""; + } +} + +function Deployables::displayErrorMsg(%item, %plyr, %slot, %error) +{ + deactivateDeploySensor(%plyr); + + %errorSnd = '~wfx/misc/misc.error.wav'; + switch (%error) + { + case $NotDeployableReason::None: + if (isObject(%plyr.client)) { + if (!spamCheck(%plyr.client)) { + %deplObj = %item.onDeploy(%plyr, %slot); + %deplObj.depTime = getSimTime(); + // TODO - temporary - remove + if ($TimedDisCenter !$= "") { + if (vectorLen(vectorDist($TimedDisCenter,%deplObj.getPosition())) < 150 && %plyr.client != nameToID(LocalClientConnection)) + %deplObj.timedDis = %deplObj.getDataBlock().schedule(1 * 5 * 1000,disassemble,0,%deplObj); + } + // ---- + messageClient(%plyr.client, 'MsgTeamDeploySuccess', ""); + return; + } + else if ($Host::Prison::DeploySpamRemoveRecentMS !$= "" && $Host::Prison::DeploySpamRemoveRecentMS > 0) { + %group = nameToID("MissionCleanup/Deployables"); + %count = %group.getCount(); + for(%i=0;%i<%count;%i++) { + %obj = %group.getObject(%i); + if (%obj.getOwner() == %plyr.client && getSimTime() - $Host::Prison::DeploySpamRemoveRecentMS < %obj.depTime) { + %obj.getDataBlock().schedule(50 * %disCount++,disassemble,%plyr,%obj); + } + } + } + } + else { + %item.onDeploy(%plyr, %slot); + messageClient(%plyr.client, 'MsgTeamDeploySuccess', ""); + return; + } + case $NotDeployableReason::NoSurfaceFound: + %msg = '\c2Item must be placed within reach.%1'; + + case $NotDeployableReason::MaxDeployed: + %msg = '\c2Your team\'s control network has reached its capacity for this item.%1'; + + case $NotDeployableReason::SlopeTooGreat: + %msg = '\c2Surface is too steep to place this item on.%1'; + + case $NotDeployableReason::SelfTooClose: + %msg = '\c2You are too close to the surface you are trying to place the item on.%1'; + + case $NotDeployableReason::ObjectTooClose: + %msg = '\c2You cannot place this item so close to another object.%1'; + + case $NotDeployableReason::NoTerrainFound: + %msg = '\c2You must place this on outdoor terrain.%1'; + + case $NotDeployableReason::NoInteriorFound: + %msg = '\c2You must place this on a solid surface.%1'; + + case $NotDeployableReason::TurretTooClose: + %msg = '\c2Interference from a nearby turret prevents placement here.%1'; + + case $NotDeployableReason::TurretSaturation: + %msg = '\c2There are too many turrets nearby.%1'; + + case $NotDeployableReason::SurfaceTooNarrow: + %msg = '\c2There is not adequate surface to clamp to here.%1'; + + case $NotDeployableReason::InventoryTooClose: + %msg = '\c2Interference from a nearby inventory prevents placement here.%1'; + + default: + %msg = '\c2Deploy failed.'; + } + messageClient(%plyr.client, 'MsgDeployFailed', %msg, %errorSnd); +} + +function ShapeBaseImageData::onActivate(%data, %obj, %slot) +{ + //Tinman - apparently, anything that uses the generic onActivate() method is a deployable. + //repair packs, cloak packs, shield, etc... all overload this method... + %data.testInvalidDeployConditions(%obj, %slot); + + //whether the test passed or not, reset the image trigger (deployables don't have an on/off toggleable state) + %obj.setImageTrigger(%slot, false); +} + + + + +function ShapeBaseImageData::onDeploy(%item, %plyr, %slot) +{ + if (%item.item $= "MotionSensorDeployable" || %item.item $= "PulseSensorDeployable") + { + %plyr.deploySensors--; + %plyr.client.updateSensorPackText(%plyr.deploySensors); + if (%plyr.deploySensors <= 0) + { + // take the deployable off the player's back and out of inventory + %plyr.unmountImage(%slot); + %plyr.decInventory(%item.item, 1); + } + } + else + { + // take the deployable off the player's back and out of inventory + %plyr.unmountImage(%slot); + %plyr.decInventory(%item.item, 1); + } + + // create the actual deployable !!!!!!!!!!!!!!!!STOP AND LOOK AT ME!!!!!!!!!!!!!!!!! ???????WHY?????? + %rot = %item.getInitialRotation(%plyr); + if (%item.deployed.className $= "DeployedTurret") + %className = "Turret"; + else + %className = "StaticShape"; + + %deplObj = new (%className)() { + dataBlock = %item.deployed; + }; + + + + // set orientation + if (%className $= "Turret") + %deplObj.setDeployRotation(%item.surfacePt, %item.surfaceNrm); + else + %deplObj.setTransform(VectorAdd(%item.surfacePt, %plac) SPC %rot); + + + // set the recharge rate right away + if (%deplObj.getDatablock().rechargeRate) + %deplObj.setRechargeRate(%deplObj.getDatablock().rechargeRate); + + // set team, owner, and handle + %deplObj.team = %plyr.client.Team; + %deplObj.setOwner(%plyr); + + // set the sensor group if it needs one + if (%deplObj.getTarget() != -1) + setTargetSensorGroup(%deplObj.getTarget(), %plyr.client.team); + + // place the deployable in the MissionCleanup/Deployables group (AI reasons) + addToDeployGroup(%deplObj); + + //let the AI know as well... + AIDeployObject(%plyr.client, %deplObj); + + // play the deploy sound + serverPlay3D(%item.deploySound, %deplObj.getTransform()); + + // increment the team count for this deployed object + + $TeamDeployedCount[%plyr.team, %item.item]++; + + if (%classname !$= "Item") + %deplObj.deploy(); + + addDSurface(%item.surface,%deplObj); + return %deplObj; +} + +function ShapeBaseImageData::getInitialRotation(%item, %plyr) +{ + return rotFromTransform(%plyr.getTransform()); +} + +function MotionSensorDeployableImage::getInitialRotation(%item, %plyr) +{ + %rotAxis = vectorNormalize(vectorCross(%item.surfaceNrm, "0 0 1")); + if (getWord(%item.surfaceNrm, 2) == 1 || getWord(%item.surfaceNrm, 2) == -1) + %rotAxis = vectorNormalize(vectorCross(%item.surfaceNrm, "0 1 0")); + return %rotAxis SPC mACos(vectorDot(%item.surfaceNrm, "0 0 1")); +} + +function MotionSensorDeployable::onPickup(%this, %pack, %player, %amount) +{ + // %this = Sensor pack datablock + // %pack = Sensor pack object number + // %player = player + // %amount = amount picked up (1) + + if (%pack.sensors $= "") + { + // assume that this is a pack that has been placed in a mission + // this case was handled in ::onInventory below (max sensors); + } + else + { + // find out how many sensor were in the pack + %player.deploySensors = %pack.sensors; + %player.client.updateSensorPackText(%player.deploySensors); + } +} + +function MotionSensorDeployable::onThrow(%this,%pack,%player) +{ + // %this = Sensor pack datablock + // %pack = Sensor pack object number + // %player = player + + %player.throwSensorPack = 1; + %pack.sensors = %player.deploySensors; + %player.deploySensors = 0; + %player.client.updateSensorPackText(%player.deploySensors); + // do the normal ItemData::onThrow stuff -- sound and schedule deletion + serverPlay3D(ItemThrowSound, %player.getTransform()); + %pack.schedulePop(); +} + +function MotionSensorDeployable::onInventory(%this,%player,%value) +{ + // %this = Sensor pack datablock + // %player = player + // %value = 1 if gaining a pack, 0 if losing a pack + + if (%player.getClassName() $= "Player") + { + if (%value) + { + // player picked up or bought a motion sensor pack + %player.deploySensors = %this.maxSensors; + %player.client.updateSensorPackText(%player.deploySensors); + } + else + { + // player dropped or sold a motion sensor pack + if (%player.throwSensorPack) + { + // player threw the pack + %player.throwSensorPack = 0; + // everything handled in ::onThrow above + } + else + { + //the pack was sold at an inventory station, or unmounted because the player + // used all the sensors + %player.deploySensors = 0; + %player.client.updateSensorPackText(%player.deploySensors); + } + } + } + Pack::onInventory(%this,%player,%value); +} + +function PulseSensorDeployable::onPickup(%this, %pack, %player, %amount) +{ + // %this = Sensor pack datablock + // %pack = Sensor pack object number + // %player = player + // %amount = amount picked up (1) + + if (%pack.sensors $= "") + { + // assume that this is a pack that has been placed in a mission + // this case was handled in ::onInventory below (max sensors); + } + else + { + // find out how many sensor were in the pack + %player.deploySensors = %pack.sensors; + %player.client.updateSensorPackText(%player.deploySensors); + } +} + +function PulseSensorDeployable::onThrow(%this,%pack,%player) +{ + // %this = Sensor pack datablock + // %pack = Sensor pack object number + // %player = player + + %player.throwSensorPack = 1; + %pack.sensors = %player.deploySensors; + %player.deploySensors = 0; + %player.client.updateSensorPackText(%player.deploySensors); + // do the normal ItemData::onThrow stuff -- sound and schedule deletion + serverPlay3D(ItemThrowSound, %player.getTransform()); + %pack.schedulePop(); +} + +function PulseSensorDeployable::onInventory(%this,%player,%value) +{ + // %this = Sensor pack datablock + // %player = player + // %value = 1 if gaining a pack, 0 if losing a pack + + if (%player.getClassName() $= "Player") + { + if (%value) + { + // player picked up or bought a motion sensor pack + %player.deploySensors = %this.maxSensors; + %player.client.updateSensorPackText(%player.deploySensors); + } + else + { + // player dropped or sold a motion sensor pack + if (%player.throwSensorPack) + { + // player threw the pack + %player.throwSensorPack = 0; + // everything handled in ::onThrow above + } + else + { + //the pack was sold at an inventory station, or unmounted because the player + // used all the sensors + %player.deploySensors = 0; + %player.client.updateSensorPackText(%player.deploySensors); + } + } + } + Pack::onInventory(%this,%player,%value); +} + +function TurretIndoorDeployableImage::getInitialRotation(%item, %plyr) +{ + %surfaceAngle = getTerrainAngle(%item.surfaceNrm); + if (%surfaceAngle > 155) + %item.deployed = TurretDeployedCeilingIndoor; + else if (%surfaceAngle > 45) + %item.deployed = TurretDeployedWallIndoor; + else + %item.deployed = TurretDeployedFloorIndoor; +} + +function TurretIndoorDeployable::onPickup(%this, %obj, %shape, %amount) +{ + // created to prevent console errors +} + +function TurretOutdoorDeployable::onPickup(%this, %obj, %shape, %amount) +{ + // created to prevent console errors +} + +function InventoryDeployable::onPickup(%this, %obj, %shape, %amount) +{ + // created to prevent console errors +} + +// --------------------------------------------------------------------------------------- +// deployed station functions +function DeployedStationInventory::onEndSequence(%data, %obj, %thread) +{ + Parent::onEndSequence(%data, %obj, %thread); + if (%thread == $DeployThread) + { + %trigger = new Trigger() + { + dataBlock = stationTrigger; + polyhedron = "-0.125 0.0 0.1 0.25 0.0 0.0 0.0 -0.7 0.0 0.0 0.0 1.0"; + }; + MissionCleanup.add(%trigger); + + %trans = %obj.getTransform(); + %vSPos = getWords(%trans,0,2); + %vRot = getWords(%trans,3,5); + %vAngle = getWord(%trans,6); + %matrix = VectorOrthoBasis(%vRot @ " " @ %vAngle + 0.0); + %yRot = getWords(%matrix, 3, 5); + %pos = vectorAdd(%vSPos, vectorScale(%yRot, -0.1)); + + %trigger.setTransform(%pos @ " " @ %vRot @ " " @ %vAngle); + + // associate the trigger with the station + %trigger.station = %obj; + %trigger.mainObj = %obj; + %trigger.disableObj = %obj; + %obj.trigger = %trigger; + } +} + +//-------------------------------------------------------------------------- +//DeployedMotionSensor: +//-------------------------------------------------------------------------- + +function DeployedMotionSensor::onDestroyed(%this, %obj, %prevState) +{ + if (%obj.isRemoved) + return; + %obj.isRemoved = true; + //%obj.hide(true); + Parent::onDestroyed(%this, %obj, %prevState); + $TeamDeployedCount[%obj.team, MotionSensorDeployable]--; + remDSurface(%obj); + %obj.schedule(500, "delete"); +} + +//-------------------------------------------------------------------------- +//DeployedPulseSensor: +//-------------------------------------------------------------------------- +function PulseSensorDeployableImage::onActivate(%data, %obj, %slot) +{ + Parent::onActivate( %data, %obj, %slot ); + //%data.testInvalidDeployConditions(%obj, %slot); +} + +function DeployedPulseSensor::onDestroyed(%this, %obj, %prevState) +{ + if (%obj.isRemoved) + return; + %obj.isRemoved = true; + Parent::onDestroyed(%this, %obj, %prevState); + $TeamDeployedCount[%obj.team, PulseSensorDeployable]--; + remDSurface(%obj); + %obj.schedule(300, "delete"); +} + +// --------------------------------------------------------------------------------------- +// deployed turret functions + +function DeployedTurret::onAdd(%data, %obj) +{ + Parent::onAdd(%data, %obj); + // auto-mount the barrel + %obj.mountImage(%data.barrel, 0, false); +} + +function DeployedTurret::onDestroyed(%this, %obj, %prevState) { + if (%obj.isRemoved) + return; + if ($Host::InvincibleDeployables != 1 || %obj.damageFailedDecon || $DestroyableTurrets == 1) { + %obj.isRemoved = true; + %turType = %this.getName(); + // either it'll be an outdoor turret, or one of the three types of indoor turret + // (floor, ceiling, wall) + if (%turType $= "TurretDeployedOutdoor") + %turType = "TurretOutdoorDeployable"; + else if (%turType $= "TurretDeployedBase") + %turType = "TurretBasePack"; + else + %turType = "TurretIndoorDeployable"; + // decrement team count + $TeamDeployedCount[%obj.team, %turType]--; + remDSurface(%obj); + %obj.schedule(700, "delete"); + } + Parent::onDestroyed(%this, %obj, %prevState); +} + +function countTurretsAllowed(%type) +{ + 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 turrets allowed + %maxPlayers = %teamPlayerCount[1] > %teamPlayerCount[2] ? %teamPlayerCount[1] : %teamPlayerCount[2]; + // each team can have 1 turret of each type (indoor/outdoor) for every 2 players + // minimum and maximums are defined in deployables.cs + %teamTurretMax = mFloor(%maxPlayers / 2); + if (%teamTurretMax < $TeamDeployableMin[%type]) + %teamTurretMax = $TeamDeployableMin[%type]; + else if (%teamTurretMax > $TeamDeployableMax[%type]) + %teamTurretMax = $TeamDeployableMax[%type]; + + return %teamTurretMax; +} + +function spamCheck(%cl) { + if ($Host::Prison::Enabled != true || $Host::Prison::DeploySpam != true || %cl.isAdmin || %cl.isSuperAdmin) + return false; + %simTime = getSimTime(); + if (%simTime - %cl.lastDeployTime > $Host::Prison::DeploySpamResetWarnCountTime * 1000) + %cl.spamCount = 0; // Reset spam count + if (%simTime - %cl.lastDeployTime < $Host::Prison::DeploySpamCheckTimeMS) { + %cl.spamCount++; + if (%cl.spamCount > $Host::Prison::DeploySpamWarnings) { + %cl.spamPunishCount++; + %cl.spamCount = 0; + %cl.lastDeployTime = 0; + %punishTime = $Host::Prison::DeploySpamTime; + %kills = 3; + if (%cl.spamPunishCount > %kills) { + if ($Host::Prison::DeploySpamMultiply > 0) { + %punishTime = (%cl.spamPunishCount - %kills) * $Host::Prison::DeploySpamTime; + if (%punishTime > $Host::Prison::DeploySpamMaxTime) + %punishTime = $Host::Prison::DeploySpamMaxTime; + } + // TODO - should really use some better formatting method... + if (%punishTime > 0) { + if (%punishTime >= 60) { + if (%punishTime > 60) { + %minutes = mFloor(%punishTime / 60); + messageClient(%cl,'msgClient','\c2You will do %1 minutes in jail for spamming deployables.',%minutes); + messageAllExcept(%cl,-1,'msgClient','\c2%1 will do %2 minutes in jail for spamming deployables.',%cl.name,%minutes); + } + else { + messageClient(%cl,'msgClient','\c2You will do 1 minute in jail for spamming deployables.'); + messageAllExcept(%cl,-1,'msgClient','\c2%1 will do 1 minute in jail for spamming deployables.',%cl.name); + } + } + else { + messageClient(%cl,'msgClient','\c2You will do %1 seconds in jail spamming.',%punishTime); + messageAllExcept(%cl,-1,'msgClient','\c2%1 will do %2 seconds in jail for spamming deployables.',%cl.name,%punishTime); + } + } + else { + messageClient(%cl,'msgClient','\c2You were put in jail for spamming deployables.'); + messageAllExcept(%cl,-1,'msgClient','\c2%1 was put in jail for spamming deployables.',%cl.name); + } + jailPlayer(%cl,false,%punishTime); + } + else { + %cl.player.scriptKill(99); + messageClient(%cl,'msgClient','\c2You were killed for spamming deployables.'); + messageAllExcept(%cl,-1,'msgClient','\c2%1 was killed for spamming deployables.',%cl.name); + } + return true; + } + // Warn player only if they've used up over half their warnings, to prevent message hud spam + else if (%cl.spamCount > mFloor(($Host::Prison::DeploySpamWarnings + 1) / 2)) { + centerPrint(%cl,"Do not spam, or face the consequences",2,1); + messageClient(%cl,'msgClient',"~wfx/misc/misc.error.wav"); + return true; + } + } + %cl.lastDeployTime = %simTime; + return false; +} + +//------------------------------ +// Deployable extra explosions +//------------------------------ + +datablock GrenadeProjectileData(DeployableFireball) { + projectileShapeName = "weapon_chaingun_ammocasing.dts"; + emitterDelay = -1; + directDamage = 0.0; + hasDamageRadius = true; + indirectDamage = 0.10; + damageRadius = 10.0; + radiusDamageType = $DamageType::Debris; + kickBackStrength = 1000; + bubbleEmitTime = 1.0; + + explosion = "PlasmaBoltExplosion"; + splash = PlasmaSplash; + explodeOnMaxBounce = true; + + velInheritFactor = 0.5; + + baseEmitter = DebrisFireEmitter; + smokeEmitter = DebrisSmokeEmitter; + + grenadeElasticity = 0.4; + grenadeFriction = 0.2; + armingDelayMS = 400; + muzzleVelocity = 20.00; + drag = 0.1; + + hasLight = true; + lightRadius = 3.0; + lightColor = "1 0.75 0.25"; +}; + +datablock StaticShapeData(DeployedLTarget) : StaticShapeDamageProfile { + className = "decontarget"; + shapeFile = "xmiscf.dts"; + + maxDamage = 0.5; + destroyedLevel = 0.5; + disabledLevel = 0.3; + + explosion = HandGrenadeExplosion; + expDmgRadius = 1.0; + expDamage = 0.05; + expImpulse = 200; + + dynamicType = $TypeMasks::StaticShapeObjectType; + deployedObject = true; + cmdCategory = "DSupport"; + cmdIcon = CMDSensorIcon; + cmdMiniIconName = "commander/MiniIcons/com_deploymotionsensor"; + targetNameTag = 'Deployed DeconTarget'; + deployAmbientThread = true; + debrisShapeName = "debris_generic_small.dts"; + debris = DeployableDebris; + heatSignature = 0; +}; + +function DeployedLTarget::onDestroyed(%this,%obj,%prevState) { + if (%obj.isRemoved) + return; + %obj.isRemoved = true; + Parent::onDestroyed(%this,%obj,%prevState); + remDSurface(%obj); + %obj.schedule(500, "delete"); + if (isObject(%obj.lMain)) { + %obj.lMain.setDamageState(Destroyed); + } +} + +function fireBallExplode(%obj,%numFb) { + + %source = %obj; + for (%i=0;%i<%numFb;%i++) { + %x = (getRandom() * 0.4) - 0.2; + %y = (getRandom() * 0.4) - 0.2; + %z = getRandom() / 2; + %vec = %x SPC %y SPC %z; + %pos = vectorAdd(posFromTransform(%obj.getTransform()),vectorScale(%vec,3)); + %p = new (GrenadeProjectile)() { + dataBlock = DeployableFireball; + initialDirection = %vec; + initialPosition = %pos; + sourceObject = %source; + sourceSlot = 1; + vehicleObject = %obj; + }; + MissionCleanup.add(%p); + } +} + +function cascade(%obj,%cascade) { + if (%obj.cascade) + %cascade = true; + if ($Host::Cascade == false && !%cascade) + return; + %list = %obj.dObj; + %count = getWordCount(%list); + for(%i=0;%i<%count;%i++) { + %obj2 = getWord(%list,%i); + if ($Host::Cascade == false) { + %obj2.cascade = true; + %random = getRandom() * 1000; + %obj2.getDataBlock().schedule(%random,disassemble,0,%obj2); + } + else { + %random = getRandom() * 1000; + %obj2.schedule(%random,setDamageState,Destroyed); + } + } + %obj.cascaded = true; +} + +// TODO - handle dup disassemblies? only allow every n seconds? + +function disassemble(%data,%plyr,%obj) { + if (!isObject(%obj)) + return; + if (%obj.lMain) { + if (isObject(%obj.lMain)) { + %obj.lMain.getDataBlock().disassemble(%plyr,%obj.lMain); + return; + } + else { + serverPlay3D(DSound,%obj.getTransform()); + %obj.schedule(500,"delete"); + remDSurface(%obj); + return; + } + } + else if (isObject(%obj.lTarget)) { + %obj.lTarget.startFade(250,0,1); + %obj.lTarget.schedule(500,"delete"); + } + %obj.isRemoved = 1; + serverPlay3D(DSound,%obj.getTransform()); + if (%obj.getType() & $TypeMasks::StaticShapeObjectType + || %obj.getType() & $TypeMasks::ItemObjectType) + %obj.startFade(500,0,1); + if (isObject(%obj.trigger)) + %obj.trigger.delete(); + if (isObject(%obj.emitter)) + %obj.emitter.delete(); + %obj.schedule(500,"delete"); + %revItem = %obj.getDataBlock().getName(); + %newPack = $ReverseDeployItem[%revItem]; + if (getWord(%newPack,0) $= "poof") + $TeamDeployedCount[%obj.team,getWord(%newPack,1)]--; + else + $TeamDeployedCount[%obj.team,%newPack]--; + cascade(%obj,false); + remDSurface(%obj); +} + +function StaticShapeData::disassemble(%data,%plyr,%obj) { + if (!isObject(%obj)) + return; + if (%obj.getDataBlock().classname $= "Generator") { + %obj.getDataBlock().losePower(%obj); + %loc = findWord($PowerList,%obj); + if (%loc !$= "") + $PowerList = listDel($PowerList,%loc); + %obj.isRemoved = true; + } + disassemble(%data,%plyr,%obj); +} + +function expertModeOn() { + exec("scripts/expertLibraries.cs"); + $Host::ExpertMode = 1; +} + +function expertModeOff() { + exec("scripts/libraries.cs"); + $Host::ExpertMode = 0; + + // Bring pack settings down from orbit + %count = ClientGroup.getCount(); + for (%i=0;%i<%count;%i++) { + %client = ClientGroup.getObject(%i); + %player = %client.player; + if (isObject(%player)) { + %player.packSet = 0; + %player.expertSet = 0; + } + } +} + +function delUndergroundDeployables(%quiet) { + %randomTime = 10000; + %group = nameToID("MissionCleanup/Deployables"); + %count = %group.getCount(); + for(%i=0;%i<%count;%i++) { + %obj = %group.getObject(%i); + if (%obj) { + %terrain = getTerrainHeight2(%obj.getPosition(),0,%obj); + if (getWord(vectorAdd(%obj.getPosition(),"0 0 0.25"),2) < getWord(%terrain,2) || %terrain $= "") { + warn("Deleting: " @ %obj @ " Name: " @ %obj.getDataBlock().getName()); + %random = getRandom() * %randomTime; + %obj.getDataBlock().schedule(%random,"disassemble",%plyr, %obj); // Run Item Specific code. + %deleted++; + } + else + %checked++; + + } + } + if (!%quiet) { + warn("Checked pieces: " @ %checked); + warn("Deleted pieces: " @ %deleted); + } + return %randomTime; +} + +function delOrphanedPieces(%quiet) { + %randomTime = 10000; + %group = nameToID("MissionCleanup/Deployables"); + %count = %group.getCount(); + for(%i=0;%i<%count;%i++) { + %obj = %group.getObject(%i); + if (!isObject(%obj.getOwner())) { + if (!%quiet) + warn("Deleting: " @ %obj @ " Name: " @ %obj.getDataBlock().getName()); + %random = getRandom() * %randomTime; + %obj.getDataBlock().schedule(%random,"disassemble",%plyr,%obj); // Run Item Specific code. + %deleted++; + } + else + %checked++; + } + if (!%quiet) { + warn("Checked pieces: " @ %checked); + warn("Deleted pieces: " @ %deleted); + } + return %randomTime; +} + +function addDSurface(%surface,%obj) { + %surface = firstWord(%surface); + %list = %surface.dObj; + %obj.dSurface = firstWord(%surface); + %list = listAdd(%list,%obj,-1); +// warn("Added obj " @ %obj @ " to surface " @ %surface); + +// For debugging +// %count = getWordCount(%list); +// for(%i=0;%i<%count;%i++) { +// %obj2 = getWord(%list,%i); +// if (!isObject(%obj2)) { +// error("surface: " @ %surface @ " - obj does not exist: " @ %obj2); +// %badIDs = %badIDs SPC %i; +// } +// } +// %list = listDel(%list,trim(%badIDs)); +//warn(%surface @ " - " @ %list); + %surface.dObj = %list; +} + +// TODO - verify +function remDSurface(%obj) { + %surface = %obj.dSurface; + if (isObject(%surface)) { + %list = %surface.dObj; + %loc = findWord(%list,%obj); + if (%loc !$= "") { + %list = listDel(%list,%loc); +// warn("Removed obj " @ %obj @ " from surface " @ %surface); + } + } + %surface.dObj = %list; + + %list = %obj.dObj; + %count = getWordCount(%list); + for(%i=0;%i<%count;%i++) { + %obj2 = getWord(%list,%i); + if (isObject(%obj2)) { + %obj2.dSurface = ""; +// warn("Removed surface " @ %obj @ " from obj " @ %obj2); + } + } +} + +function GameBase::setOwner(%obj,%plyr,%client,%guid) { + if (!%client) + %client = %plyr.client; + if (!%guid) + %guid = %client.guid; + %obj.owner = %client; + %obj.ownerGUID = %guid; +} + +function GameBase::getOwner(%obj) { + if (isObject(%obj.owner)) + return %obj.owner; + %guid = %obj.ownerGUID; + if (!%guid) + %guid = %obj.lTarget.ownerGUID; + if (!%guid) + %guid = %obj.lMain.ownerGUID; + if (%guid) { + %count = ClientGroup.getCount(); + for (%i=0;%i<%count;%i++) { + %client = ClientGroup.getObject(%i); + if (%client.guid == %guid) + return %client; + } + } + return ""; +} diff --git a/scripts/do_not_delete/Dfunctions.cs b/scripts/do_not_delete/Dfunctions.cs new file mode 100644 index 0000000..4b52d3b --- /dev/null +++ b/scripts/do_not_delete/Dfunctions.cs @@ -0,0 +1,1431 @@ +//Custom functions by Mostlikely +//There's a lot of outdated stuff here +//But those things are needed for basic deploying until I can update the code. +//Be sure to mail any questions to "sebastiaan_keek@hotmail.com" + + +// Basic dynamic movement script. +// Fps reduction and lag producing [[A bit]] +// To be expanded/uniformed in later versions + +$Pi = 3.1415926535897932; +$AnimationTime = 150; + +function lev(%num) { + if (%num < 0) + return -1; + else + if (%num > 0) + return 1; + else + return 0; +} + +//function abs(%num) { +// %num = %num * lev(%num); +// if (%num == 0) +// %num = 0; +// return %num; +//} + +function vlev(%vec) +{ +return lev(getWord(%vec,0)) SPC lev(getWord(%vec,1)) SPC lev(getWord(%vec,2)); +} + +function vAbs(%vec) { + return mAbs(getWord(%vec,0)) SPC mAbs(getWord(%vec,1)) SPC mAbs(getWord(%vec,2)); +} + +//Basic test.. don't use this function jet... it won't stop + +function DynamicRotate(%obj,%vec,%crot) +{ +%vec = vectorNormalize(%vec); +//%rot = getrot(getRotation(%obj)); +//%rx = getWord(%rot,0); +//%ry = getWord(%rot,1); +//%rz = getWord(%rot,2); +//%xr = %rx+ getWord(%pace,0); +//%yr = %ry + getWord(%pace,1); +//%zr = %rz + getWord(%pace,2); +%oldrot = rotFromTransform(%Obj.getTransform()); +//Schedule(50, %obj,"dynamicRotate2", %obj, %vec, %crot,%oldrot); +} + +function DynamicRotate2(%obj,%vec,%crot,%oldrot) +{ +%vec = vectorNormalize("0 0 1"); +%crot = %crot + 0.1; +%newrot = %vec SPC %crot; +%setrot = rotAdd(%oldrot,%newrot); +setRotation(%obj, %setrot); +Schedule(50, %obj,"dynamicRotate2", %obj, %vec, %crot,%oldrot); +} + +//DynamicScale +//Better than dynamicmove... +//To be expanded. + +function DynamicScale(%obj,%time,%pace,%end) +{ +%scale = %obj.GetScale(); +%sx = getWord(%scale,0); +%sy = getWord(%scale,1); +%sz = getWord(%scale,2); +%newx = %sx + getWord(%pace,0); +%newy = %sy + getWord(%pace,1); +%newz = %sz + getWord(%pace,2); + + +%done = 1; +if (mAbs(%newx - getWord(%end,0)) > mAbs(%sx - getWord(%end,0))) + %xscale = getWord(%end,0); // If we didn't make progress.. +else + { + %xscale = %newx; // If we did make progress.. + %done = 0; + } +if (mAbs(%newy - getWord(%end,1)) > mAbs(%sy - getWord(%end,1))) + %yscale = getWord(%end,1); // If we didn't make progress.. +else + { + %yscale = %newy; // If we did make progress.. + %done = 0; + } +if (mAbs(%newz - getWord(%end,2)) > mAbs(%sz - getWord(%end,2))) + %zscale = getWord(%end,2); // If we didn't make progress.. +else + { + %zscale = %newz; // If we did make progress.. + %done = 0; + } + +%newscale = %xscale SPC %yscale SPC %zscale; +%obj.setScale(%newscale); +if (%done == 0) + schedule(%time, %obj,"dynamicScale", %obj, %time, %pace, %end ,%plyr); +} + +//Returns xyz rotation from tribes uniformalized 4 digit rotation. + +function getrot(%rotation) +{ +%xr = getWord(%rotation,0)*getWord(%rotation,3); +%yr = getWord(%rotation,1)*getWord(%rotation,3); +%zr = getWord(%rotation,2)*getWord(%rotation,3); +return %xr SPC %yr SPC %zr; +} + +//Returns tribes rotation from xyz rotation in an outdated way. + +function setrot(%rot) +{ +%mat = MatrixCreateFromEuler(%rot); +return getWord(%mat,3) SPC getWord(%mat,4) SPC getWord(%mat,5) SPC getWord(%mat,6); +} + +//Controlled version setrot +//Soon to be used in deploying. + +function setrot2(%rot) +{ +%vn = vectorNormalize(%rot); +if (getWord(%vn,0) != 0) +%zn = getWord(%rot,0) / getWord(%vn,0); +else if (getWord(%vn,1) != 0) +%zn = getWord(%rot,1) / getWord(%vn,1); +else if (getWord(%vn,2) != 0) +%zn = getWord(%rot,2) / getWord(%vn,2); +else +%zn = 0; +return %vn SPC %zn; +} + +//Returns a rotation from a normal that matches the normal and faces up the slope + +// for loadscreen.cs +if ($MissionDisplay != true) + %of = true; + +function slopfromnrm(%up) +{ + +%x=getWord(%up,0); +%y=getWord(%up,1); +%z=getWord(%up,2); +%xy = Mpow((Mpow(%x,2)+Mpow(%y,2)),0.5); +%zrot = MAtan(%y,%x)-1.5708; +%xrot = -MAtan(%xy,%z); +return %xrot SPC "0" SPC %zrot; +} + +//expanded version of slopfromnrm +//Doesn't not work properly.. to be updated. + +function rotfromnrm(%up,%le) +{ +%le = vectorScale(vectorright(%up,%le),-1); +%fo = VectorCross(%up,%le); +%x = getWord(%fo,0); +%y = getWord(%fo,1); +%zrot = MAtan(%y,%x); +%up = rotatenormal(%up,0,0,-1 * %zrot); +%fo = rotatenormal(%fo,0,0,-1 * %zrot); +%le = rotatenormal(%le,0,0,-1 * %zrot); +%x = getWord(%fo,0); +%y = getWord(%fo,2); +%yrot = MAtan(%y,%x); +%up = rotatenormal(%up,0,-1 * %yrot,0); +%fo = rotatenormal(%fo,0,-1 * %yrot,0); +%le = rotatenormal(%le,0,-1 * %yrot,0); +%x = getWord(%up,1); +%y = getWord(%up,2); +%xrot = MAtan(%x,%y); +%up = rotatenormal(%up, %xrot,0,0); +%fo = rotatenormal(%fo, %xrot,0,0); +%le = rotatenormal(%le, %xrot,0,0); +return %xrot SPC %yrot SPC %zrot + 3.14159; +} + +// for loadscreen.cs +if (%of == true) { + return; +} + +//Should rotate things in the same order as tribes2 does. +function rotatenormal(%vector,%xr,%yr,%zr) +{ + // z > x + // z > y + // y > x +//x rot +%x = getWord(%vector,0); +%y = getWord(%vector,1); +%z = getWord(%vector,2); +%vector = %x SPC rotatedot(%y SPC %z, %xr); +//y rot +%x = getWord(%vector,0); +%y = getWord(%vector,1); +%z = getWord(%vector,2); +%vector = getWord(rotatedot(%x SPC %z,%yr),0) SPC %y SPC getWord(rotatedot(%x SPC %z,%yr),1); +//z rot +%x = getWord(%vector,0); +%y = getWord(%vector,1); +%z = getWord(%vector,2); +%vector = rotatedot(%x SPC %y, %zr) SPC %z; +return %vector; +} + +//2dimensional rotation... used in some calculations + +function rotatedot(%vector,%rot) +{ +%nx = MCos(%rot) * getWord(%vector,0) + -1 * MSin(%rot) * getWord(%vector,1); +%ny = MSin(%rot) * getWord(%vector,0) + MCos(%rot) * getWord(%vector,1); +%nvector = %nx SPC %ny; +return %nvector; +} + +//Returns the proper y as when a proper x and problematic y are introduced + +function vectorright(%mainvec,%chanvec) +{ +%temp = VectorCross(%mainvec,%chanvec); +return vectorNormalize(VectorCross(%mainvec,%temp)); +} + +//Returns the vector that %vector is heading in %direction + +function vectorproject(%vector,%direction) +{ +%v = %vector;//VectorSub(%item.surfacePt,%item.surface.getTransform()); +%a = %direction; //VectorCross(%item.surface.up,%item.surfaceNrm); +return vectorScale(%a,(VectorDot(%a,%v) / MPow (VectorLen(%a),2))); +} + +//Returns the lengt of %vector in %direction + +function vectorcouple(%vector,%direction) +{ +%v = %vector;//VectorSub(%item.surfacePt,%item.surface.getTransform()); +%a = %direction; //VectorCross(%item.surface.up,%item.surfaceNrm); +return (VectorDot(%a,%v) / MPow (VectorLen(%a),2)); +} + +function rotAdd(%rotation1,%rotation2) +{ +%v1 = "0 0 0" SPC %rotation1; +%v2 = "0 0 0" SPC %rotation2; +// This is the function verified to sometimes return "inf" or "nan". The others are checked for safety's sake +%v3 = validateVal(MatrixMultiply(%v1,%v2)); +%axis = vectorNormalize(getWords(%v3,3,5)); +return %axis SPC getWord(%v3,6); +} + +function realrot(%obj,%rotation) +{ +%rot = rot(%Obj); +//[Note] Old notation caused trouble. +//Not sure if the new one is totaly accurate.. but it works ;) +//return rotAdd(rotAdd(%rot,%rotation),invrot(%rot)); +%axis = realvec(%obj,getWords(%rotation,0,2)); +return %axis SPC getWord(%rotation,3); +} + +function virrot(%obj,%rotation) +{ +%rot = rot(%Obj); +//return rotAdd(rotAdd(invrot(%rot),%rotation),%rot); +%axis = virvec(%obj,getWords(%rotation,0,2)); +return %axis SPC getWord(%rotation,3); +} + +function remoteRotate(%mobj,%rot,%cobj,%mcenter) +{ +%oldrot = rot(%mObj); +%oldpos = vectorAdd(pos(%mObj),%center); +%center = vectorAdd(pos(%cObj),Realvec(%cobj,VectorMultiply(%mcenter,vectorScale(realSize(%cobj),-1)))); +%rrot = realrot(%cobj,%rot); +%newpos = vectorAdd(validateVal(MatrixMulPoint("0 0 0" SPC %rrot,vectorSub(%oldpos,%center))),%center); +return %newpos SPC rotAdd(%rrot,%oldrot); +} + +function realSize(%obj) { + if (%obj.getType() & $TypeMasks::StaticShapeObjectType) + %ws = (%obj.getDataBlock().getName() $= "DeployedWoodSpine"); + if (isCubic(%obj) || %ws) { + %scale = %obj.GetScale(); + if (%ws) + return vectorDivide(%scale,1.845 SPC 2 SPC 1.744); // Update spine.cs if changed! + else + return (getWord(%scale,0) * 4) SPC (getWord(%scale,1) * 3) SPC (getWord(%scale,2) * 0.5); + } +} + +function isCubic(%obj) { + if (!isObject(%obj)) + return; + if (!(%obj.getType() & $TypeMasks::StaticShapeObjectType)) + return; + %shape = %obj.getDatablock().shapefile; + if (getSubStr(%shape,1,strLen(%shape)) $= "miscf.dts") + return 1; + else + return ""; +} + +function realvec(%obj,%vec) { + %rot = rot(%Obj); + return validateVal(MatrixMulVector("0 0 0" SPC %rot ,%vec)); +} + +function virvec(%obj,%vec) +{ +%rot = rot(%Obj); +%rot = getWord(%rot,0) SPC getWord(%rot,1) SPC getWord(%rot,2) SPC (-1*getWord(%rot,3) ); +return validateVal(MatrixMulVector("0 0 0" SPC %rot ,%vec)); +} + +function vectorangle(%vec1,%vec2) +{ +return MACos(VectorDot(%vec1,%vec2)/(VectorLen(%vec1)*VectorLen(%vec2))); +} + +function vectormultiply(%vec1,%vec2) +{ +return getWord(%vec1,0) * getWord(%vec2,0) SPC getWord(%vec1,1)* getWord(%vec2,1) SPC getWord(%vec1,2)* getWord(%vec2,2); +} + +// An updated version of this function is located further down in the file - JackTL +//function vectordivide(%vec1,%vec2) +//{ +//return getWord(%vec1,0) / getWord(%vec2,0) SPC getWord(%vec1,1) / getWord(%vec2,1) SPC getWord(%vec1,2) / getWord(%vec2,2); +//} + +function vectordescale(%vec1,%scale) +{ +return %scale/getWord(%vec1,0) SPC %scale/getWord(%vec1,1) SPC %scale /getWord(%vec1,2); +} + +function getface(%obj,%vec) +{ +%rot = getWords(rot(%Obj),0,2) SPC -1 * getWord(rot(%Obj),3); +return validateVal(MatrixMulVector("0 0 0" SPC %rot ,%vec)); +} + +function floorvec(%vec,%size) +{ +%mod = vLev(%vec); +%vec = vAbs(vectorScale(%vec,%size)); +%vec = Mfloor(getWord(%vec,0)) SPC Mfloor(getWord(%vec,1)) SPC Mfloor(getWord(%vec,2)); +return VectorMultiply(vectorScale(%vec,(1/%size)),%mod); +} + +function invface(%face) +{ +return VectorSub("1 1 1",vAbs(%face)); +} + +function getfacesize(%obj,%face) +{ +return VectorMultiply(vAbs(invface(%face)),realSize(%obj)); +} + +function breach(%val,%border) +{ +if (%border < 0) +return %val; +if (%val > %border) +return (%val-%border); +else +return 0; +} + +function topface(%vec) +{ +if (mAbs(getWord(%vec,0)) >= mAbs(getWord(%vec,1)) + mAbs(getWord(%vec,2))) +return getWord(%vec,0) SPC "0 0"; +if (mAbs(getWord(%vec,1)) >= mAbs(getWord(%vec,0)) + mAbs(getWord(%vec,2))) +return "0" SPC getWord(%vec,1) SPC "0"; +if (mAbs(getWord(%vec,2)) >= mAbs(getWord(%vec,0)) + mAbs(getWord(%vec,1))) +return "0 0" SPC getWord(%vec,2); +} + +function pullaxis(%vec1,%vec2) +{ +%face = invface(%vec2); +%hit = vectorNormalize(topface(vectormultiply(%vec1,%face))); +return vectorNormalize(VectorCross(%hit,%vec2)); +} + +function pullobject(%obj,%vec1,%vec2,%angle,%center) { + if (!isObject(%obj)) + return; + %pos = pos(%Obj); + %rot = rot(%Obj); + %vec = vectorSub(%vec1,%pos); + %vec = virVec(%obj,%vec); + %vec = vectorAdd(vectorDivide(%vec,vectorScale( realSize(%obj),0.5 ) ),"0 0 -1"); + %axis = pullAxis(%vec,%vec2); + if (!isCubic(%obj) && %obj.getDataBlock().getName() !$= "DeployedWoodSpine") + %axis = "0 0 1"; + if (%obj.getType() & $TypeMasks::ForceFieldObjectType) + return; + %obj.setTransform(remoteRotate(%obj,%axis SPC %angle,%obj,%center)); + checkAfterRot(%obj); +} + +function rotateSection(%obj,%list,%rotation) { + %count = getWordCount(%list); + for (%id = 0; %id < %count; %id++) { + %obj2 = getWord(%list,%id); + if (isObject(%obj2)) { + %obj2.setTransform(remoteRotate(%obj2,%rotation,%obj)); + checkAfterRot(%obj2); + } + } +} + +function checkAfterRot(%obj) { + if (!$Host::AllowUnderground) { + %terrain = getTerrainHeight2(%obj.getPosition()); + if (getWord(%obj.getPosition(),2) < getWord(%terrain,2) || %terrain $= "") + %obj.setPosition(%terrain); + } + if (isObject(%obj.pzone)) + %obj.pzone.setTransform(%obj.getTransform()); + if (isObject(%obj.trigger)) + adjustTrigger(%obj); + if (isObject(%obj.beam)) + tp_adjustBeam(%obj); + if (isObject(%obj.holo)) + adjustHolo(%obj); + if (isObject(%obj.light)) + adjustLight(%obj); + if (isObject(%obj.lMain)) + adjustLMain(%obj); + if (%obj.getDataBlock().needsPower) { + %obj.powerCount = ""; + checkPowerObject(%obj); + } + // TODO - handle gens +} + +function adjustTrigger(%obj) { + // TODO - adjust trigger for InventoryDeployable + %dataBlockName = %obj.getDataBlock().getName(); + if (%dataBlockName $= "StationInventory") { + %adjust = vectorMultiply(realVec(%obj,"0 0 1"),"1 1 3"); + %adjustUp = getWord(%adjust,2); + %adjust = getWords(%adjust,0,1) SPC ((%adjustUp * 0.5) + (mAbs(%adjustUp) * -0.5)); + %obj.trigger.setTransform(vectorAdd(%obj.getPosition(),%adjust) SPC "0 0 0"); // %obj.rotation); + } +} + +// Oh hush, it works. :) +function adjustLMain(%obj) { + %dataBlockName = %obj.lMain.getDataBlock().getName(); + if (getSubStr(%dataBlockName,0,18) $= "DeployedDecoration") { + %pos = %obj.getPosition(); + %rot = %obj.getRotation(); + %nrm = realVec(%obj,"0 0 1"); + %nrm2 = realVec(%obj,"1 0 0"); + %nrm3 = realVec(%obj,"0 1 0"); + %no = trim(getSubStr(%dataBlockName,18,2)); + if (%no < 3) { + %nrm2 = vectorScale(%nrm2,-1); + %pos = vectorAdd(%pos,vectorScale(%nrm3,2.80)); + %pos = vectorAdd(%pos,vectorScale(%nrm,0.25)); + %rot = rotAdd(%rot,"1 0 0" SPC $Pi / 2); + %rot = rotAdd(%rot,"0 1 0" SPC $Pi); + } + else if (%no > 2 && %no < 6) { + %pos = vectorAdd(%pos,vectorScale(%nrm,-0.2)); + if (%no == 3) { + %pos = vectorAdd(%pos,vectorScale(%nrm2,0.14)); + %pos = vectorAdd(%pos,vectorScale(%nrm3,-0.51)); + } + if (%no == 4) { + %pos = vectorAdd(%pos,vectorScale(%nrm2,-0.25)); + %pos = vectorAdd(%pos,vectorScale(%nrm3,0.4)); + } + if (%no == 5) { + %pos = vectorAdd(%pos,vectorScale(%nrm2,-0.05)); + %pos = vectorAdd(%pos,vectorScale(%nrm3,-0.4)); + %rot = rotAdd(%rot,"0 0 -1" SPC $Pi / 4); + } + } + else if (%no > 11 && %no < 16) { + %pos = vectorAdd(%pos,vectorScale(%nrm,1)); + %pos = vectorAdd(%pos,vectorScale(%nrm3,23.1)); + %rot = rotAdd(%rot,"-1 0 0" SPC $Pi / 2); + } + %obj.lMain.setTransform(%pos SPC %rot); + } + else if (getSubStr(%dataBlockName,0,18) $= "DeployedEscapePod") { + adjustEscapePod(%obj.lMain); + %epod = %obj.lMain.podVehicle; + if (isObject(%epod) && %epod.used == false) + %epod.delete(); + } +} + +function invrot(%rot) +{ +return vectorScale(getWord(%rot,0) SPC getWord(%rot,1) SPC getWord(%rot,2),-1) SPC getWord(%rot,3); +} + +//Tones down the outer parts +//In real cube size. + +function cubefix(%cube,%point,%joint) +{ +%limit = vectorScale(realSize(%cube),0.5); +%px = getWord(%point,0) - ( lev( getWord(%point,0) ) * breach( mAbs(getWord(%point,0)) , getWord(%limit,0)-getWord(%joint,0) ) ); +%py = getWord(%point,1) - ( lev( getWord(%point,1) ) * breach( mAbs(getWord(%point,1)) , getWord(%limit,1)-getWord(%joint,1) ) ); +%pz = getWord(%point,2) - ( lev( getWord(%point,2) ) * breach( mAbs(getWord(%point,2)) , getWord(%limit,2)-getWord(%joint,2) ) ); +return %px SPC %py SPC %pz; +} + +//Same as cubefix +//Only in virtual cube size. + +function vircubefix(%point,%joint) +{ +%limit = "1 1 1"; +%px = getWord(%point,0) - ( lev( getWord(%point,0) ) * breach( mAbs(getWord(%point,0)) , getWord(%limit,0)-getWord(%joint,0) ) ); +%py = getWord(%point,1) - ( lev( getWord(%point,1) ) * breach( mAbs(getWord(%point,1)) , getWord(%limit,1)-getWord(%joint,1) ) ); +%pz = getWord(%point,2) - ( lev( getWord(%point,2) ) * breach( mAbs(getWord(%point,2)) , getWord(%limit,2)-getWord(%joint,2) ) ); +return %px SPC %py SPC %pz; +} + +//Obj = Surface. +//face = surfaceNrm (Real) +//point = surfacePt (Real) +//joint = dobj surface size (Real) +//center = relative center for surface (Virtual) + +function sidelink(%obj,%face,%point,%joint,%center) +{ +%loc = pos(%Obj); + +//Fitting All stuff to virtual space +%relpoint = VectorSub(%point,%loc); +%virpoint = virvec(%obj,%relpoint); +%virpoint = VectorDivide(%virpoint,vectorScale( realSize(%obj),0.5 )); +%virpoint = vectorAdd(%virpoint,vectorScale(%center,2)); + +%virjoint = VectorDivide( %joint,vectorScale( realSize(%obj),1 )); +%virface = virvec(%obj,%face); + +//Desiding which side should be linked to. +%sidedir = pullaxis(%virpoint,%virface); +%side = VectorCross(%sidedir,%virface); + +//Keeping the movement on that side within bounds. +%virpoint = vircubefix(%virpoint,%virjoint); +%virpoint = VectorMultiply( %virpoint, vAbs(%sidedir)); + +//Fitting the new location next to the object. +%overpull = VectorMultiply(vectorScale(%side,-1),vectorAdd(%virjoint,"1 1 1")); + + +//Getting it all together. +%mask = vectorAdd(vectorAdd(%virpoint,%virface),%overpull); + + +//Returning to real space. +%virpoint = vectorAdd(%mask,vectorScale(%center,-2)); + +%virpoint = VectorMultiply(vectorScale(realSize(%obj),0.5),%virpoint); + +%relpoint = realvec( %obj , %virpoint); + +//Also returning the side used. +//echo(floorvec(%virface,1)); +if (vAbs(vlev(floorvec(%virface,100))) $= "0 1 0") +%goodside = VectorCross(%virface,"0 0 1"); +else +%goodside = VectorCross(%virface,"0 1 0"); + +%realside = vectorNormalize(realvec(%obj,%side)); +%dirside = vectorNormalize(realvec(%obj,%goodside)); + +return vectorAdd(%loc,%relpoint) SPC %realside SPC %dirside; +} + + + +//Function returns the fited placement. +//Obj = Surface object. +//Face = surface normal. (Virtual) +//Point = Surface Hit point. (Real) +//Joint = Surface size placement object. (Real) +//Center = Models t2 center relative to the real center. (Virtual) + + +function link(%obj,%face,%point,%joint,%center) +{ +%loc = pos(%Obj); +%relpoint = VectorSub(%point,%loc); + + %virpoint = virvec(%obj,%relpoint); + + %adjust = VectorMultiply(%center,realSize(%obj)); + + %virpoint = vectorAdd(%virpoint,%adjust); + + + %virpoint = cubefix(%obj,%virpoint,%joint); + + %virpoint = VectorMultiply( %virpoint, invface(%face) ); + + %mask = VectorMultiply(vectorScale(realSize(%obj),0.5), %face); + + %virpoint = vectorAdd(%mask,%virpoint); + + %virpoint = vectorAdd(%virpoint,vectorScale(%adjust,-1)); + + %relpoint = realvec( %obj , %virpoint); + +return vectorAdd(%loc,%relpoint); +} + + + +function slopeRot(%vec) +{ +if (vAbs(floorvec(%vec,100)) $= "0 0 1") + return "1 0 0" SPC $Pi/2 - (lev(getWord(%vec,2))*$Pi/2); +else + %secv = "0 0 1"; +%axis = VectorCross(%vec,%secv); +%angle = VectorAngle(%vec,%secv); +return validateVal(vectorNormalize(%axis) SPC %angle); +} + +function intRot(%rot,%vec) +{ +%vec1 = validateVal(MatrixMulVector("0 0 0" SPC invrot(%rot),%vec)); +%vec1 = vectorNormalize(getWord(%vec1,0) SPC getWord(%vec1,1) SPC "0"); +%angle = MAtan(getWord(%vec1,1),getWord(%vec1,0)); +return "0 0 -1" SPC %angle; +} + +//Function returns rotation. +//Vec1 = Alignment direction. +//Vec2 = Facing direction. + +function fullrot(%vec,%vec2) +{ +%rot = slopeRot(%vec); +return rotAdd(%rot,intRot(%rot,%vec2)); +} + +function rayDist(%vecs,%sizes,%mask,%obj) { + if (!%mask) + %mask = -1; + %obj = mAbs(%obj); + %start = getWords(%vecs,0,2); + %dir = vectorNormalize(getWords(%vecs,3,5)); + %min = getWord(%sizes,0); + %norm = getWord(%sizes,1); + %max = getWord(%sizes,2); + %endPos = vectorAdd(%start,vectorScale(%dir,%max)); + + %res = containerRayCast(%start, %endPos, %mask, %obj); + + if (%res) { + if (%res.getType() & $TypeMasks::TerrainObjectType) + %res = containerRayCast(vectorAdd(%start,"0 0 0.1"), %endPos, %mask, %obj); + if (%res > 0) { + %hit = getWords(%res,1,3); + %dist = vectorDist(%start,%hit); + } + } + if (%dist <= 0) + %dist = %norm; + if (%dist < %min) + %dist = %min; + return %dist; +} + + +//Function Returns scale and transform of a wall. +//Vec1 = Start,Fitdirection1,Fitdirection2. +//Sizes = Minsize & thickness, No hit size, Max fit size. +//Center = Models t2 center relative to the real center. + +function pad(%vecs,%sizes,%center,%mask,%obj) { + if (!%mask) + %mask = $AllObjMask; + %obj = mAbs(%obj); + %start1 = getWords(%vecs,0,2); + %dir1 = vectorNormalize(getWords(%vecs,3,5)); + %dir2 = vectorNormalize(getWords(%vecs,6,8)); + %dir3 = vectorNormalize(VectorCross(%dir1,%dir2)); + %height = rayDist(%start1 SPC %dir1,%sizes,%mask,%obj); + %start2 = vectorAdd(vectorScale(%dir1,%height/2),%start1); + %right = rayDist(%start2 SPC %dir2,%sizes,%mask,%obj); + %left = rayDist(%start2 SPC vectorScale(%dir2,-1),%sizes,%mask,%obj); + if ((%left + %right)>getWord(%sizes,2)) { + %lef = %left; + %left = %left-(((%left+%right)-getWord(%sizes,2))/2); + %right = %right-(((%lef+%right)-getWord(%sizes,2))/2); + } + %scale1 = %height; + %scale2 = (%left+%right); + %scale3 = getWord(%sizes,0); + %scale = %scale1 SPC %scale2 SPC %scale3; + + %moveDist1 = vectorScale( %dir2, ( ( (%left+%right)/2 ) - %left ) ); + %moveDist2 = vectorScale( %dir1, %height/2 ); + %moveDist3 = "0 0 0";//vectorScale(%dir3,getWord(%sizes,0)*getWord(%center,2)); + + %Adjust1 = vectorScale(%dir1,%scale1*getWord(%center,0)); + %Adjust2 = vectorScale(%dir2,%scale2*getWord(%center,1)); + %Adjust3 = vectorScale(%dir3,%scale3*getWord(%center,2)); + + %moveDist = vectorAdd(vectorAdd(%movedist1,%movedist2),%movedist3); + %Adjust = vectorAdd(vectorAdd(%Adjust1,%Adjust2),%Adjust3); + %TotalMove = vectorAdd(%movedist,%adjust); + + %rot = slopeRot(%dir1); + %rot2 = rotAdd("0 0 1" SPC (1/2 * $Pi),"0 1 0" SPC (1/2 * $Pi)); + %rot = rotAdd(%rot,intRot(%rot,%dir2)); + %rotation = rotAdd(%rot,%rot2); + return %scale SPC vectorAdd(%TotalMove,%start1) SPC %rotation; +} + +//// [[[[List operations]]]]; + +function createList(%size) { + for(%id = 0; %id < %size; %id++) + %list = %list SPC "0"; + return trim(%list); +} + +function listAdd(%list,%words,%location) { + if (%location == -1) + %list = %list SPC %words; + else if (%location == 0) + %list = %words SPC %list; + else + %list = getWords(%list,0,%location-1) SPC %words SPC getWords(%list,%location,getWordCount(%list)); + return trim(%list); +} + +function listReplace(%list,%words,%location) { + if (%location == 0) + %list = %words SPC getWords(%list,1,getWordCount(%list)); + else if (%location == getWordCount(%list)) + %list = getWords(%list,0,%location) SPC %words; + else + %list = getWords(%list,0,%location-1) SPC %words SPC getWords(%list,%location+1,getWordCount(%list)); + return trim(%list); +} + +function listDel(%list,%ids) { + %size = getWordCount(%list); + for(%id = 0; %id < %size; %id++) { + if (findWord(%ids,%id) $= "") + %tempList = %tempList SPC getWord(%list,%id); + } + return trim(%tempList); +} + +function listSort(%list,%sortList) { + for (%id = 0; %id < getWordCount(%sortList); %id++) + %tempList = %tempList SPC getWord(%list,getWord(%sortList,%id)); + return trim(%tempList); +} + +function listBuild(%list,%sortList) { + %tempList = createList(getWordCount(%sortList)); + for (%id = 0; %id < getWordCount(%sortList); %id++) + %tempList = listReplace(%tempList,getWord(%list,%id),getWord(%sortList,%id)); + return trim(%tempList); +} + +function findWord(%list,%words) { + %result = ""; + %size = getWordCount(%list); + %size2 = getWordCount(%words); + for (%marker = 0; %marker < %size; %marker++) { + for (%find = 0; %find < %size2; %find++) { + if (getWord(%words,%find) $= getWord(%list,%marker)) + %result = %result SPC %marker; + } + } + return trim(%result); +} + +//function stripEndSpaces(%list) { +// if (getSubStr(%list,0,1) $= " ") +// %list = getSubStr(%list,1,strLen(%list)-1); +// return stripTrailingSpaces(%list); +//} + + +function pos(%loc,%mod) { + if (!isObject(%loc)) + return; + if (!%mod) + return posFromTransform(%loc.getTransform()); + %mainmod = getWord(%mod,0); + if (%mainmod $="o") { + if (%loc) { + %trans = %loc.getTransform(); + %xyz = posFromTransform(%trans); + %mod =getWords(%mod,1,getWordCount(%mod)); + } + } + else if (%mainmod $="t") { + if (%loc) { + %xyz = posFromTransform(%loc); + %mod =getWords(%mod,1,getWordCount(%mod)); + } + } + for(%i = 0; %i < getWordCount(%mod); %i++) + %result = %result SPC poshelp1(%xyz,getWord(%mod,%i)); + return %result; +} + + +function poshelp1(%xyz,%id) +{ +if (%id $= "x") + return getWord(%xyz,0); +if (%id $= "y") + return getWord(%xyz,1); +if (%id $= "z") + return getWord(%xyz,2); + + return getWord(%xyz,%id); +} + + +function rot(%loc,%mod) { + if (!isObject(%loc)) + return; + if (!%mod) + return rotFromTransform(%loc.getTransform()); + %mainmod = getWord(%mod,0); + if (%mainmod $="o") { + if (%loc) { + %trans = %loc.getTransform(); + %xyz = rotFromTransform(%trans); + %mod =getWords(%mod,1,getWordCount(%mod)); + } + } + else if (%mainmod $="t"){ + if (%loc){ + %xyz = rotFromTransform(%loc); + %mod =getWords(%mod,1,getWordCount(%mod)); + } + } + for(%i = 0; %i < getWordCount(%mod); %i++) + %result = %result SPC rothelp1(%xyz,getWord(%mod,%i)); + return %result; +} + + +function rothelp1(%xyz,%id) +{ +if (%id $= "x") + return getWord(%xyz,0); +if (%id $= "y") + return getWord(%xyz,1); +if (%id $= "z") + return getWord(%xyz,2); +if (%id $= "a") + return getWord(%xyz,3); +return getWord(%xyz,%id); +} + +function getjoint(%item) +{ +if (%item.item.joint) + return %item.item.joint; +else + return "0.5 0.5 0.5"; +} + +// + +function findhit(%plyr) +{ + $MaxDeployDistance = %item.maxDeployDis; + $MinDeployDistance = %item.minDeployDis; + + %surface = Deployables::searchView(%plyr, + $MaxDeployDistance, + ($TypeMasks::TerrainObjectType | + $TypeMasks::InteriorObjectType)); + if (%surface) + { + %surfacePt = posFromRaycast(%surface); + %surfaceNrm = normalFromRaycast(%surface); + return %surface SPC %surfacept SPC %surfacenrm; + } +return ""; +} + +function getTerrainHeight2(%loc,%rail,%obj) { + %mask = $TypeMasks::TerrainObjectType | $TypeMasks::InteriorObjectType; + if (%rail $= "" || %rail $= "0") + %rail = "0 0 1"; + //else if (getWord(%rail,2) <= 0) + //%rail = vAbs(%rail); + %rail = vectorNormalize(%rail); + %start = vectorAdd(%loc,vectorScale(%rail,-100000)); + %end = vectorAdd(%loc,vectorScale(%rail,100000)); + %res = containerRayCast(%start, %end, %mask,%obj); + if (%res) + return getWords(%res,1,3); + else + return ""; +} + +// Animations + +function groundpop(%obj,%rail,%time) +{ +%oldpos = pos(%obj); +%rail = vectorNormalize(%rail); +%top = VectorLen(VectorMultiply(realSize(%obj),vAbs(vlev(floorvec( virvec(%obj,%rail),1000))))); +%newpos = vectorAdd(GetHeight(pos(%obj),%rail),vectorScale(%rail,(-0.5 * %top) -0.2)); +%movement = VectorSub(pos(%obj),%newpos); +%speed = (VectorLen(%movement) / %time)*150; +%tick = vectorScale(vectorNormalize(%movement),%speed); +%obj.setTransform(%newpos SPC rot(%obj)); +dynamicMove(%obj,%tick,%time/150,%oldpos); +} + +function DynamicMove(%obj,%tick,%times,%end) +{ +%pos = posFromTransform(%Obj.getTransform()); +%rot = rotFromTransform(%Obj.getTransform()); +if (%times < 1) + %tick = vectorScale(%tick,%times); +%newpos = vectorAdd(%pos,%tick); +%Obj.setTransform(%newpos SPC %rot); +%times=%times-1; +if (%times > 0) + schedule($AnimationTime, %obj, "dynamicMove", %obj, %tick,%times,%end); +else + %Obj.setTransform(%end SPC %rot); +} + +function getRandomVec() { + %vec = getRandom() - 0.5 SPC getRandom() - 0.5 SPC getRandom() - 0.5; + return vectorNormalize(%vec); +} + +function validateVal(%val) { + if (strStr(%val,"nan") != -1 || strStr(%val,"inf") != -1) { + %val = ""; + error("Rot error no. " @ $RotErrors++); + } + return %val; +} + +//////// Dfunctions additon Volume 2 +//////// 1-9-2002 + +///Returns the vector off by a certain amount. +function VectorMiss(%vec) +{ +%x = (getRandom() - 0.5) * 2 * 3.1415926 * %miss/10000; +%y = (getRandom() - 0.5) * 2 * 3.1415926 * %miss/10000; +%z = (getRandom() - 0.5) * 2 * 3.1415926 * %miss/10000; +%mat = MatrixCreateFromEuler(%x @ " " @ %y @ " " @ %z); +return validateVal(MatrixMulVector(%mat, %vec)); +} + +//Returns the Volume of the object's box +function GameBase::GetVolume(%obj) +{ +%size = VectorMultiply(VectorSub(GetWords(%obj.getObjectbox(),0,2),GetWords(%obj.getObjectbox(),3,5)),%obj.getScale()); +return VectorDot(%size,%size); +} + +//Returns the surfaces of the object's box +function GameBase::GetSurface(%obj) +{ +%size = VectorMultiply(VectorSub(GetWords(%obj.getObjectbox(),0,2),GetWords(%obj.getObjectbox(),3,5)),%obj.getScale()); +%sizex = GetWord(%size,1)*GetWord(%size,2); +%sizey = GetWord(%size,0)*GetWord(%size,2); +%sizez = GetWord(%size,0)*GetWord(%size,1); +return %sizex SPC %sizey SPC %sizez; +} + +//Limits the value between boundries + +function limit(%value,%min,%max) +{ +if (%value > %max && %max !$= "") + return %max; +if (%value < %min && %min !$= "") + return %min; +return %value; +} + +//Returns -1 or 1 + +function randomlev() +{ + if(getRandom(1)) + return 1; + else + return -1; +} + +//Returns if the target is an forcefield +function GameBase::isforcefield(%target) +{ +if (%target && isObject(%target)) + { + if (%target.getDatablock().classname $= "forcefield") + return 1; + } +return ""; +} + + +//A random bool going from always 0 when the imputed value is below min +//To awlays 1 when the imputed value is above max +function Change(%value,%min,%max) +{ +return ((%value-%min)/(%max-%min)) > getRandom(); +} + +//Returns a random player +function Randomplayer() +{ +if (!ClientGroup.getCount()) + return ""; + +%client = ClientGroup.getObject(GetRandom()*ClientGroup.getCount()); +return %client.player; +} + +//Retuns a random deployable +function randomdeployable() +{ +%group = nameToID("MissionCleanup/Deployables"); +%count = %group.getCount(); + +if (!%count) + return ""; + +return %group.getObject(getRandom()*%count); +} + +//Checks if there's line of sight between objects +function los(%obj1,%obj2,%offset1,%offset2,%mask) { + if (!%mask) + %mask = -1; + %start = pos(%obj1); + %end = pos(%obj2); + if (%offset1) + %start = vectorAdd(%start,realvec(%obj1,%offset1)); + if (%offset2) + %end = vectorAdd(%end,realvec(%obj2,%offset2)); + %res = containerRayCast(%start,%end,%mask,%obj1); + return (%res == %obj2); +} + + +//Returns the closests player to the given location +function closestPlayer(%location) { + %dis = ""; + + if (!ClientGroup.getCount()) + return ""; + + %tplayer = ""; + for( %c = 0; %c < ClientGroup.getCount(); %c++ ) { + %client = ClientGroup.getObject(%c); + %player = %client.player; + %pos = pos(%player); + %dist = vectorDist(%location,%pos); + if ($MTC_Loaded = true) { + if (!%dis || %dist < %dis && MTCCleanTarget(%player)) { + %tplayer = %player; + %dis = %dist; + } + } + else { + if (!%dis || %dist < %dis) { + %tplayer = %player; + %dis = %dist; + } + } + } + return %tplayer SPC %dist; +} + +//Moderate + +//Returns Location information about the location. +function aboveground(%pos,%work,%obj) + { + ///1 Give ground under feet + %mask = $TypeMasks::TerrainObjectType | $TypeMasks::InteriorObjectType; + %res1 = containerRayCast(%pos, GetWords(%pos,0,1) SPC "-10000", %mask,0); + if (%res1) + { + if (%res1.getClassName() $= TerrainBlock) + %ground = 1; + else + %ground = 2; + } + else + %ground = ""; + + ///2 Give cieling + if (%work > 0) + { + %res2 = containerRayCast(%pos,vectorAdd(%pos,"0 0 10000"), %mask,0); + if (%res2) + { + if (%res2.getClassName() $= TerrainBlock) + %cieling = 1; + else + %cieling = 2; + } + else + %cieling = ""; + + } + if (%work > 1) + { + if (%res1) + %down = VectorDist(posFromRaycast(%res1),%pos); + if (%res2) + %up = VectorDist(posFromRaycast(%res2),%pos); + } + + +/// void = 0 +/// terrain = 1 +/// Interior = 2 +/// Ground-Cieling; + +%answer = %ground + %cieling*3; +switch$ (%answer) { + case 0: + return "underground" SPC %down SPC %up; //0-0 + case 1: + return "open" SPC %down SPC %up; //1-0 + case 2: + return "roof" SPC %down SPC %up; //2-0 + case 3: + return "underground" SPC %down SPC %up; //0-1 + case 4: + return "odd-t" SPC %down SPC %up; //1-1 + case 5: + return "odd-int" SPC %down SPC %up; //2-1 + case 6: + return "underbuilding" SPC %down SPC %up; //0-2 + case 7: + return "shadow" SPC %down SPC %up; //1-2 + case 8: + return "inside" SPC %down SPC %up; //2-2 + } +} + + +//Returns wetehr or not we can see the top of the object above ground. +function GameBase::seetop(%obj) +{ +%res = containerRayCast(vectorAdd(%obj.getWorldboxcenter(),"0 0 1000"),%obj.getWorldboxcenter(),-1,0); + if (GetWord(%res,0) == %obj) + return %res; + else + return ""; +} + +///////////////////////// +/////////new since 24-8// +///////////////////////// + +///Dfunctions + +function MicroAdjust(%pos) +{ +%offset = (GetRandom()*0.02 - 0.01) SPC (GetRandom()*0.02 - 0.01) SPC (GetRandom()*0.02 - 0.01); +return vectorAdd(%pos,%offset); +} + +function MatrixDot(%vector,%matrix) +{ +%count1 = GetWordCount(%vector); +%count2 = GetWordCount(%matrix); +if (%count1 == 2 && %count2 == 4) + return VectorDot(GetWords(%matrix,0,1),%vector) SPC VectorDot(GetWords(%matrix,2,3),%vector); +if (%count1 == 3 && %count2 == 9) + return VectorDot(GetWords(%matrix,0,2),%vector) SPC VectorDot(GetWords(%matrix,3,5),%vector) SPC VectorDot(GetWords(%matrix,6,8),%vector); +} + +function MatrixMult(%vector,%matrix) +{ +%v1 = vectorScale(GetWords(%matrix,0,2),GetWord(%vector,0)); +%v2 = vectorScale(GetWords(%matrix,3,5),GetWord(%vector,1)); +%v3 = vectorScale(GetWords(%matrix,6,8),GetWord(%vector,2)); +return vectorAdd(%v1,vectorAdd(%v2,%v3)); +} + +function TransPose(%matrix) +{ +%count = GetWordCount(%matrix); +if (%count == 4) + return GetWord(%matrix,0) SPC GetWord(%matrix,2) SPC GetWord(%matrix,1) SPC GetWord(%matrix,3); +else if (%count == 9) + return GetWord(%matrix,0) SPC GetWord(%matrix,3) SPC GetWord(%matrix,5) SPC GetWord(%matrix,1) SPC GetWord(%matrix,4) SPC GetWord(%matrix,6) SPC GetWord(%matrix,2) SPC GetWord(%matrix,5) SPC GetWord(%matrix,7); +} + + +function dCross(%vector,%dir) +{ +if (!%dir) + %dir =1; +return %dir*GetWord(%vector,1) SPC %dir* -1*GetWord(%vector,0); +} + + +function MatrixfromVector(%vector,%dir) +{ +%count = GetWordCount(%vector); +if (%count == 2) + { + return %vector SPC dCross(%vector,%dir); + } +else if (%count == 3) + { + %x = GetWord(%vector,0); + %y = GetWord(%vector,1); + %z = GetWord(%vector,2); + %x2 = -1*((%x * %y)/(Mpow(%x,2)+Mpow(%y,2)+Mpow(%z,2))); + %y2 = (mPow(%x,2) * mPow(%z,2))/(Mpow(%x,2)+Mpow(%y,2)+Mpow(%z,2)); + %z2 = -1*((%y * %z)/(Mpow(%x,2)+Mpow(%y,2)+Mpow(%z,2))); + %x3 = -1*((%x * %z)/(Mpow(%x,2)+Mpow(%z,2))); + %z3 = mPow(%x,2)/(Mpow(%x,2)+Mpow(%z,2)); + return %vector SPC %x2 SPC %y2 SPC %z2 SPC %x3 SPC "0" SPC %z3; + } +} + +function Inverse(%matrix) +{ +%count = GetWordCount(%matrix); +if (%count == 4) + { + %a = GetWord(%matrix,0); + %b = GetWord(%matrix,1); + %c = GetWord(%matrix,2); + %d = GetWord(%matrix,3); + %prod = (-1*%b * %c + %a * %d); + return %d/%prod SPC -1*%b/%prod SPC -1*%c / %prod SPC %a / %prod; + } +else if (%count == 9) + { + %a = GetWord(%matrix,0); + %b = GetWord(%matrix,1); + %c = GetWord(%matrix,2); + %e = GetWord(%matrix,3); + %f = GetWord(%matrix,4); + %g = GetWord(%matrix,5); + %h = GetWord(%matrix,6); + %i = GetWord(%matrix,7); + %j = GetWord(%matrix,8); + %prod = -1*%c*%e*%g+%b*%f*%g+%c*%d*%h-%a*%f*%h-%b*%d*%i+%a*%e*%i; + %a1 = (-1*%f*%h+%e*%i)/%prod; + %b1 = (-1*%c*%h-%b*%i)/%prod; + %c1 = (-1*%c*%e+%b*%f)/%prod; + %d1 = (-1*%f*%g-%d*%i)/%prod; + %e1 = (-1*%c*%g+%a*%i)/%prod; + %f1 = (-1*%c*%d-%a*%f)/%prod; + %g1 = (-1*%e*%g+%d*%h)/%prod; + %h1 = (-1*%b*%g-%a*%h)/%prod; + %i1 = (-1*%b*%d+%a*%e)/%prod; + return %a1 SPC %b1 SPC %c1 SPC %d1 SPC %e1 SPC %f1 SPC %g1 SPC %h1 SPC %i1; + } +} + +function GameBase::GetShapeSize(%obj) +{ +return VectorSub(getWords(%obj.getObjectBox(),3,5),getWords(%obj.getObjectBox(),0,2)); +} + +function GameBase::GetRealSize(%obj) +{ +%return = VectorMultiply(%obj.getScale(),%obj.getShapeSize()); +if (%obj.getdatablock().getname() $="DeployedCrate11") //for pad swap + %return = vectorMultiply(%return,0.121951 SPC 0.238095 SPC 0.243902); +return %return; +} + +function GameBase::SetRealSize(%obj,%size) +{ +%scale = vectordivide(%size,%obj.getShapeSize()); +if (%obj.getdatablock().getname() $="DeployedCrate11") //for pad swap + %scale = vectorMultiply(%scale,8.20002 SPC 4.2 SPC 4.1); +%obj.setScale(%scale); +} + +function GameBase::SetWorldBoxCenter(%obj,%location) +{ +%obj.setEdge(%location,"0 0 0"); +} + +function GameBase::SetEdge(%obj,%location,%offset) +{ +%VirCenter = vectorScale(vectorAdd(getWords(%obj.getObjectBox(),3,5),getWords(%obj.getObjectBox(),0,2)),0.5); +%VirOffset = VectorMultiply(vectorScale(%offset,0.5),%obj.getShapeSize()); +%realoffset = RealVec(%obj,VectorMultiply(vectorAdd(%VirCenter,%VirOffset),%obj.getScale())); +%pos = vectorAdd(%location,vectorScale(%realoffset,-1)); +%obj.setTransform(%pos SPC rot(%obj)); +} + +function GameBase::GetEdge(%obj,%offset) +{ +%VirCenter = vectorScale(vectorAdd(getWords(%obj.getObjectBox(),3,5),getWords(%obj.getObjectBox(),0,2)),0.5); +%VirOffset = VectorMultiply(vectorScale(%offset,0.5),%obj.getShapeSize()); +%realoffset = RealVec(%obj,VectorMultiply(vectorAdd(%VirCenter,%VirOffset),%obj.getScale())); +return vectorAdd(GetWords(%obj.getTransform(),0,2),%realoffset); +} + + +///////////////////////// +/////////new since 1-9// +///////////////////////// + +//Replacement function for old calcb +//returns the changes damage instead of the coverage! + +function calcBuildingInWay2(%position, %targetObject,%damage,%radius) + { + %targetPos = %targetObject.getWorldBoxCenter(); + $SolidCo = 1; + %sourcePos = %position; + + %mask = $TypeMasks::StaticObjectType; + %found = containerRayCast(%sourcePos, %targetPos, %mask,%lastfound); + while (%found && %found != %targetObject && %damage > 0) + { + //Theoretically this should never happen + if ((%found.getClassName() $= InteriorInstance) || (%found.getClassName() $= TSStatic)) + return 0; + %dist = VectorDist(%sourcepos,getWords(%found,1,3)); + %amount = (1.0 - ((%dist / %radius) * 0.88)) * %damage; + %damage = %amount - (%found.getDamageLeft() * %SolidCo); + %lastfound = %found; + %lastsourcepos = GetWords(%found,1,3); + %found = containerRayCast(%lastsourcePos, %targetPos, %mask,%lastfound); + } + return Limit(%damage,0); +} + +//Returns the highest value of the vector only + +function topvec(%vec) { + %x = getWord(%vec,0); + %y = getWord(%vec,1); + %z = getWord(%vec,2); + if (mAbs(%x) >= mAbs(%y) && mAbs(%x) >= mAbs(%z)) + return %x SPC "0 0"; + else if (mAbs(%y) >= mAbs(%x) && mAbs(%y) >= mAbs(%z)) + return "0" SPC %y SPC "0"; + else + return "0 0" SPC %z; +} + +//Changed Vector Divide, to be more stable. + +function VectorDivide(%vec1,%vec2) +{ +%x1 = getWord(%vec1,0); +%y1 = getWord(%vec1,1); +%z1 = getWord(%vec1,2); +%x2 = getWord(%vec2,0); +%y2 = getWord(%vec2,1); +%z2 = getWord(%vec2,2); +%x3 = 0; +%y3 = 0; +%z3 = 0; +if (%x1 != 0||%x2 != 0) + %x3 = %x1/%x2; +if (%y1 != 0||%y2 != 0) + %y3 = %y1/%y2; +if (%z1 != 0||%z2 != 0) + %z3 = %z1/%z2; +return %x3 SPC %y3 SPC %z3; +} + + +function VirpassVector(%obj,%vec) +{ +%virvec = floorvec(vectorNormalize(VirVec(%obj,%vec)),1000); +%mask = floorvec(VectorMultiply(vectorScale(vectorNormalize(%virvec),1/mPow(2,0.5)),%obj.getRealSize()),1000); +%inoutvec = VectorMultiply( vectorNormalize( TopVec( VAbs( VectorDivide( %virvec,%mask ) ))),%obj.getRealSize()); +%pass = vectorScale( %virvec,VectorLen( VectorDivide( %inoutvec,%virvec ) ) ); +return %pass; +} + +function getpassVector(%obj,%vec) +{ +return RealVec(%obj,VirpassVector(%obj,%vec)); +} + +/////////The amout of substance you'd be crossing of an object if you went through the object in %vec direction. +/////////ie. going through the front of a 10 10 1 wall would return 1 going to the side would return 10. + +function getpassLength(%obj,%vec) +{ +return VectorLen(getpassVector(%obj,%vec)); +} + +//////// END Dfunctions additon Volume 2 +//////// 1-9-2002 diff --git a/scripts/do_not_delete/loadscreen.cs.dso b/scripts/do_not_delete/loadscreen.cs.dso new file mode 100644 index 0000000000000000000000000000000000000000..7a75cd56689999c838b2a414faa1439be77da755 GIT binary patch literal 3195 zcma);S%@4}6o&6a&BU0+-H3{n*pp;5iIZ_lia1G6SI?xiJJXrzxW%9~-M44TRChI9 z)k)e77X+1vyC^Q8NH8J+MGysFeGt?KAM`;%K~Yh`4SWzSzf;R>@xi3O{_j2K-g8f# zd#aOTN~y~hDdp>Ct?1dcLbL8wyqxRkW}sXQB`>n6vfUO_Up035)oESpxLP%0zwA|0 zI>>n)R>k{A+g_)|j>yDD@sCa3rmKN+{A?lTHG{V2y1Evfo*XoDc%Ro)eO|q;8rt{m zDV^k$$#vS2Ny+hjhb5V0U^#xvwY$6QhE|!Ko*$UzDC2le?CW$pTHi;)MW@LkjJdY1 zIf0*UD0kX=vg5e5)KJlO!?GKkKE_FL)RKLu%t3@pEfuGsi%!F#I=*fn(Cvyo6hzN7 zu5CBTPYSCt)p^NRx-HEfr#a>7IHt<9+PZFN&&{cgk#ws&0tzEZ7 z+MUJ-1)Okh=TRbK(Vo<<*i@ezJ)qnP^_HiNuO&0bqN2$-SGd5Rnif`8+10=~Uv4<6hU zOzUdu-W2R#s`wipwx{WEAHLxPw(C^Q&09Dp_0bVEyJ@Gs!7Go;Xy!~BP0}N5l%`X6 zk_^))+}-hlsF1Q^rj1O_G7M=VBkrQuKnEGpt0X3dg>{g2GF<7WIo^SR5&jHqoQN9C zn9xB$d-xK6?;c+pliH>P#$+c5kiawigHBMLHt2Tk@0&R!4O4MizIoiqdoA5^y{JxLjI__7s({9&P-uAm`-1ygkD~e(dS%s02 zLT*p7a-(T%^IKkPNSTU3$DbaG?{oevy5)FN}YrOMXgvbCfvrV-Yd%VlBD zeXPnWS=7^~Hkw)0r!Lu%QT=>Q>%CW8NsP#y2JG2-Zf`4^M4^V+)qmlJtCM{v7vk7q zw}-IGI#VKB=g4=oCwE@iS{KEY*fR-PZx*blO9keog7qZa0qaY$4O`J#H@2$xJ4OZT zr+C$Dz`xUgQ94%mDhC&=@GgWH;l4z-M;adxZkju}Aer;XYu!jrP&Z^MXj)bQCc{v z;etF~{Es{iA0OoZ<#96`muG4BOLj>6N9Qf?UW3URIfeYa+SPdV+8u$z{@Er`oUvL#7+yO8;fLK;p=JmHktp5E@S>_GXEa!Xa14cS^o|CEb~X<4!9Mrhcavc zIe#Vm!MY#eHQ=K@;p_cm`~mt3oQVAe^mBL{-hc;z?dmC1elTu_lbAn*-iKolO^x`pikj?Uvo)2HLz=jI^iBI}U_Ph@7CgUUM(PaDzD!nNGqC5#E zi`T&uiR}?oa$N&=Gv)~8!u{X@W_1h5|Dt3pJz|5@Q2O&u@IiXYf}23jlAi8D7Nj3# z?`0tC=o$0YS5&$ literal 0 HcmV?d00001 diff --git a/scripts/editor.cs b/scripts/editor.cs new file mode 100644 index 0000000..44e0660 --- /dev/null +++ b/scripts/editor.cs @@ -0,0 +1,113 @@ +//----------------------------------------------------------------------------- +// Torque Game Engine +// +// Copyright (c) 2001 GarageGames.Com +// Portions Copyright (c) 2001 by Sierra Online, Inc. +//----------------------------------------------------------------------------- + + +//------------------------------------------------------------------------------ +// Hard coded images referenced from C++ code +//------------------------------------------------------------------------------ + +// editor/SelectHandle.png +// editor/DefaultHandle.png +// editor/LockedHandle.png + + +//------------------------------------------------------------------------------ +// Functions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Mission Editor +//------------------------------------------------------------------------------ + +function Editor::create() +{ + // Not much to do here, build it and they will come... + // Only one thing... the editor is a gui control which + // expect the Canvas to exist, so it must be constructed + // before the editor. + new EditManager(Editor) + { + profile = "GuiContentProfile"; + horizSizing = "right"; + vertSizing = "top"; + position = "0 0"; + extent = "640 480"; + minExtent = "8 8"; + visible = "1"; + setFirstResponder = "0"; + modal = "1"; + helpTag = "0"; + open = false; + }; +} + + +function Editor::onAdd(%this) +{ + // Basic stuff + exec("scripts/cursors.cs"); + exec("scripts/EditorProfiles.cs"); + + // Tools + exec("scripts/editor.bind.cs"); + exec("gui/ObjectBuilderGui.gui"); + + // New World Editor + exec("gui/EditorGui.gui"); + exec("scripts/EditorGui.cs"); + exec("gui/AIEWorkingDlg.gui"); + + // World Editor + exec("gui/WorldEditorSettingsDlg.gui"); + + // Terrain Editor + exec("gui/TerrainEditorVSettingsGui.gui"); + exec("gui/HelpDlg.gui"); + exec("scripts/help.cs"); + + // do gui initialization... + EditorGui.init(); + + // + exec("scripts/editorRender.cs"); +} + +function Editor::checkActiveLoadDone() +{ + if(isObject(EditorGui) && EditorGui.loadingMission) + { + Canvas.setContent(EditorGui); + EditorGui.loadingMission = false; + return true; + } + return false; +} + +//------------------------------------------------------------------------------ +function toggleEditor(%make) +{ + if (%make) + { + if (!$missionRunning) + { + MessageBoxOK("Mission Required", "You must load a mission before starting the Mission Editor.", ""); + return; + } + +// $testcheats = 1; + if (!isObject(Editor)) + { + Editor::create(); + MissionCleanup.add(Editor); + } + if (Canvas.getContent() == EditorGui.getId()) + Editor.close(); + else + Editor.open(); + } +} + diff --git a/scripts/expertLibraries.cs b/scripts/expertLibraries.cs new file mode 100644 index 0000000..d54d1de --- /dev/null +++ b/scripts/expertLibraries.cs @@ -0,0 +1,148 @@ +//Contain basic data libraries. +//Soon to be updated with more usefull stuff. + +// NOTE - any changes here must be considered in libraries.cs !!! + +//** New format of information ** + +$packSettings["spine"] = 18; +$packSetting["spine",0] = "0.5 0.5 0.1 10 cm in height"; +$packSetting["spine",1] = "0.5 0.5 0.25 25 cm in height"; +$packSetting["spine",2] = "0.5 0.5 0.5 50 cm in height"; +$packSetting["spine",3] = "0.5 0.5 1 1 meter in height"; +$packSetting["spine",4] = "0.5 0.5 1.5 1.5 meters in height"; +$packSetting["spine",5] = "0.5 6 160 auto adjusting"; +$packSetting["spine",6] = "0.5 8 160 pad"; +$packSetting["spine",7] = "0.5 8 160 wooden pad"; +$packSetting["spine",8] = "0.5 0.5 4 4 meters in height"; +$packSetting["spine",9] = "0.5 0.5 8 8 meters in height"; +$packSetting["spine",10] = "0.5 0.5 20 20 meters in height"; +$packSetting["spine",11] = "0.5 0.5 40 40 meters in height"; +$packSetting["spine",12] = "0.5 0.5 80 80 meters in height"; +$packSetting["spine",13] = "0.5 0.5 100 100 meters in height"; +$packSetting["spine",14] = "0.5 0.5 160 160 meters in height"; +$packSetting["spine",15] = "0.5 0.5 400 400 meters in height"; +$packSetting["spine",16] = "0.5 0.5 1000 1k meters in height"; +$packSetting["spine",17] = "0.5 0.5 2000 2k meters in height"; +$packSetting["spine",18] = "0.5 0.5 4000 4k meters in height"; + +$packSettings["mspine"] = 18; +$packSetting["mspine",0] = "1 1 0.1 2 2 0.5 10 cm in height"; +$packSetting["mspine",1] = "1 1 0.25 2 2 0.5 25 cm in height"; +$packSetting["mspine",2] = "1 1 0.5 2 2 0.5 50 cm in height"; +$packSetting["mspine",3] = "1 1 1 2 2 0.5 1 meters in height"; +$packSetting["mspine",4] = "1 1 1.5 2 2 0.5 1.5 meters in height"; +$packSetting["mspine",5] = "1 8 160 2 2 0.5 auto adjusting"; +$packSetting["mspine",6] = "1 8 160 2 2 0.5 normal rings"; +$packSetting["mspine",7] = "1 8 160 8 8 0.5 platform rings"; +$packSetting["mspine",8] = "1 1 4 2 2 0.5 4 meters in height"; +$packSetting["mspine",9] = "1 1 8 2 2 0.5 8 meters in height"; +$packSetting["mspine",10] = "1 1 20 2 2 0.5 20 meters in height"; +$packSetting["mspine",11] = "1 1 40 2 2 0.5 40 meters in height"; +$packSetting["mspine",12] = "1 1 80 2 2 0.5 80 meters in height"; +$packSetting["mspine",13] = "1 1 100 2 2 0.5 100 meters in height"; +$packSetting["mspine",14] = "1 1 160 2 2 0.5 160 meters in height"; +$packSetting["mspine",15] = "1 1 400 2 2 0.5 400 meters in height"; +$packSetting["mspine",16] = "1 1 1000 2 2 0.5 1k meters in height"; +$packSetting["mspine",17] = "1 1 2000 2 2 0.5 2k meters in height"; +$packSetting["mspine",18] = "1 1 4000 2 2 0.5 4k meters in height"; + +$packSettings["floor"] = 11; +$packSetting["floor",0] = "0.1 0.1 40 0.1 0.1 0.1 10 cm wide"; +$packSetting["floor",1] = "1 1 40 1 1 1 1 meter wide"; +$packSetting["floor",2] = "4 4 40 4 4 4 4 meters wide"; +$packSetting["floor",3] = "10 10 20 10 10 10 10 meters wide"; +$packSetting["floor",4] = "20 20 20 20 20 20 20 meters wide"; +$packSetting["floor",5] = "30 30 20 30 30 30 30 meters wide"; +$packSetting["floor",6] = "40 40 20 40 40 40 40 meters wide"; +$packSetting["floor",7] = "50 50 20 50 50 50 50 meters wide"; +$packSetting["floor",8] = "60 60 20 60 60 60 60 meters wide"; +$packSetting["floor",9] = "100 100 40 100 100 100 100 meters wide"; +$packSetting["floor",10] = "400 400 40 400 400 400 400 meters wide"; +$packSetting["floor",11] = "1000 1000 40 1000 1000 1000 1k meters wide"; + +$packSettings["walk"] = 74; +$packSetting["walk",0] = "0 flat"; +$packSetting["walk",1] = "1 Sloped 1 degrees up"; +$packSetting["walk",2] = "-1 Sloped 1 degrees down"; +$packSetting["walk",3] = "5 Sloped 5 degrees up"; +$packSetting["walk",4] = "-5 Sloped 5 degrees down"; +$packSetting["walk",5] = "10 Sloped 10 degrees up"; +$packSetting["walk",6] = "-10 Sloped 10 degrees down"; +$packSetting["walk",7] = "15 Sloped 15 degrees up"; +$packSetting["walk",8] = "-15 Sloped 15 degrees down"; +$packSetting["walk",9] = "20 Sloped 20 degrees up"; +$packSetting["walk",10] = "-20 Sloped 20 degrees down"; +$packSetting["walk",11] = "25 Sloped 25 degrees up"; +$packSetting["walk",12] = "-25 Sloped 25 degrees down"; +$packSetting["walk",13] = "30 Sloped 30 degrees up"; +$packSetting["walk",14] = "-30 Sloped 30 degrees down"; +$packSetting["walk",15] = "35 Sloped 35 degrees up"; +$packSetting["walk",16] = "-35 Sloped 35 degrees down"; +$packSetting["walk",17] = "40 Sloped 40 degrees up"; +$packSetting["walk",18] = "-40 Sloped 40 degrees down"; +$packSetting["walk",19] = "45 Sloped 45 degrees up"; +$packSetting["walk",20] = "-45 Sloped 45 degrees down"; +$packSetting["walk",21] = "50 Sloped 50 degrees up"; +$packSetting["walk",22] = "-50 Sloped 50 degrees down"; +$packSetting["walk",23] = "55 Sloped 55 degrees up"; +$packSetting["walk",24] = "-55 Sloped 55 degrees down"; +$packSetting["walk",25] = "60 Sloped 60 degrees up"; +$packSetting["walk",26] = "-60 Sloped 60 degrees down"; +$packSetting["walk",27] = "65 Sloped 65 degrees up"; +$packSetting["walk",28] = "-65 Sloped 65 degrees down"; +$packSetting["walk",29] = "70 Sloped 70 degrees up"; +$packSetting["walk",30] = "-70 Sloped 70 degrees down"; +$packSetting["walk",31] = "75 Sloped 75 degrees up"; +$packSetting["walk",32] = "-75 Sloped 75 degrees down"; +$packSetting["walk",33] = "80 Sloped 80 degrees up"; +$packSetting["walk",34] = "-80 Sloped 80 degrees down"; +$packSetting["walk",35] = "85 Sloped 85 degrees up"; +$packSetting["walk",36] = "-85 Sloped 85 degrees down"; +$packSetting["walk",37] = "90 Sloped 90 degrees up"; +$packSetting["walk",38] = "-90 Sloped 90 degrees down"; +$packSetting["walk",39] = "95 Sloped 95 degrees up"; +$packSetting["walk",40] = "-95 Sloped 95 degrees down"; +$packSetting["walk",41] = "100 Sloped 100 degrees up"; +$packSetting["walk",42] = "-100 Sloped 100 degrees down"; +$packSetting["walk",43] = "105 Sloped 105 degrees up"; +$packSetting["walk",44] = "-105 Sloped 105 degrees down"; +$packSetting["walk",45] = "110 Sloped 110 degrees up"; +$packSetting["walk",46] = "-110 Sloped 110 degrees down"; +$packSetting["walk",47] = "115 Sloped 115 degrees up"; +$packSetting["walk",48] = "-115 Sloped 115 degrees down"; +$packSetting["walk",49] = "120 Sloped 120 degrees up"; +$packSetting["walk",50] = "-120 Sloped 120 degrees down"; +$packSetting["walk",51] = "125 Sloped 125 degrees up"; +$packSetting["walk",52] = "-125 Sloped 125 degrees down"; +$packSetting["walk",53] = "130 Sloped 130 degrees up"; +$packSetting["walk",54] = "-130 Sloped 130 degrees down"; +$packSetting["walk",55] = "135 Sloped 135 degrees up"; +$packSetting["walk",56] = "-135 Sloped 135 degrees down"; +$packSetting["walk",57] = "140 Sloped 140 degrees up"; +$packSetting["walk",58] = "-140 Sloped 140 degrees down"; +$packSetting["walk",59] = "145 Sloped 145 degrees up"; +$packSetting["walk",60] = "-145 Sloped 145 degrees down"; +$packSetting["walk",61] = "150 Sloped 150 degrees up"; +$packSetting["walk",62] = "-150 Sloped 150 degrees down"; +$packSetting["walk",63] = "155 Sloped 155 degrees up"; +$packSetting["walk",64] = "-155 Sloped 155 degrees down"; +$packSetting["walk",65] = "160 Sloped 160 degrees up"; +$packSetting["walk",66] = "-160 Sloped 160 degrees down"; +$packSetting["walk",67] = "165 Sloped 165 degrees up"; +$packSetting["walk",68] = "-165 Sloped 165 degrees down"; +$packSetting["walk",69] = "170 Sloped 170 degrees up"; +$packSetting["walk",70] = "-170 Sloped 170 degrees down"; +$packSetting["walk",71] = "175 Sloped 175 degrees up"; +$packSetting["walk",72] = "-175 Sloped 175 degrees down"; +$packSetting["walk",73] = "180 Sloped 180 degrees up"; +$packSetting["walk",74] = "-180 Sloped 180 degrees down"; + +$packSettings["jumpad"] = 6; +$packSetting["jumpad",0] = "500 5 boost"; +$packSetting["jumpad",1] = "1000 10 boost"; +$packSetting["jumpad",2] = "1500 15 boost"; +$packSetting["jumpad",3] = "2500 25 boost"; +$packSetting["jumpad",4] = "5000 50 boost"; +$packSetting["jumpad",5] = "7500 75 boost"; +$packSetting["jumpad",6] = "10000 100 boost"; diff --git a/scripts/forceField.cs b/scripts/forceField.cs new file mode 100644 index 0000000..7cc96e1 --- /dev/null +++ b/scripts/forceField.cs @@ -0,0 +1,290 @@ +//-------------------------------------------------------------------------- +// Force fields: +// +// accept the following commands: +// open() +// close() +// +//-------------------------------------------------------------------------- + + +datablock ForceFieldBareData(defaultForceFieldBare) +{ + fadeMS = 1000; + baseTranslucency = 0.30; + powerOffTranslucency = 0.0; + teamPermiable = false; + otherPermiable = false; + color = "0.0 0.55 0.99"; + powerOffColor = "0.0 0.0 0.0"; + targetNameTag = 'Force Field'; + targetTypeTag = 'ForceField'; + + texture[0] = "skins/forcef1"; + texture[1] = "skins/forcef2"; + texture[2] = "skins/forcef3"; + texture[3] = "skins/forcef4"; + texture[4] = "skins/forcef5"; + + framesPerSec = 10; + numFrames = 5; + scrollSpeed = 15; + umapping = 1.0; + vmapping = 0.15; +}; + + +datablock ForceFieldBareData(defaultTeamSlowFieldBare) +{ + fadeMS = 1000; + baseTranslucency = 0.3; + powerOffTranslucency = 0.0; + teamPermiable = true; + otherPermiable = false; + color = "0.28 0.89 0.31"; + powerOffColor = "0.0 0.0 0.0"; + targetTypeTag = 'ForceField'; + + texture[0] = "skins/forcef1"; + texture[1] = "skins/forcef2"; + texture[2] = "skins/forcef3"; + texture[3] = "skins/forcef4"; + texture[4] = "skins/forcef5"; + + framesPerSec = 10; + numFrames = 5; + scrollSpeed = 15; + umapping = 1.0; + vmapping = 0.15; +}; + +datablock ForceFieldBareData(defaultAllSlowFieldBare) +{ + fadeMS = 1000; + baseTranslucency = 0.30; + powerOffTranslucency = 0.0; + teamPermiable = true; + otherPermiable = true; + color = "1.0 0.4 0.0"; + powerOffColor = "0.0 0.0 0.0"; + targetTypeTag = 'ForceField'; + + texture[0] = "skins/forcef1"; + texture[1] = "skins/forcef2"; + texture[2] = "skins/forcef3"; + texture[3] = "skins/forcef4"; + texture[4] = "skins/forcef5"; + + framesPerSec = 10; + numFrames = 5; + scrollSpeed = 15; + umapping = 1.0; + vmapping = 0.15; +}; + +datablock ForceFieldBareData(defaultNoTeamSlowFieldBare) +{ + fadeMS = 1000; + baseTranslucency = 0.30; + powerOffTranslucency = 0.0; + teamPermiable = false; + otherPermiable = true; + color = "1.0 0.0 0.0"; + powerOffColor = "0.0 0.0 0.0"; + targetTypeTag = 'ForceField'; + + texture[0] = "skins/forcef1"; + texture[1] = "skins/forcef2"; + texture[2] = "skins/forcef3"; + texture[3] = "skins/forcef4"; + texture[4] = "skins/forcef5"; + + framesPerSec = 10; + numFrames = 5; + scrollSpeed = 15; + umapping = 1.0; + vmapping = 0.15; +}; + +datablock ForceFieldBareData(defaultSolidFieldBare) +{ + fadeMS = 1000; + baseTranslucency = 0.30; + powerOffTranslucency = 0.0; + teamPermiable = false; + otherPermiable = false; + color = "1.0 0.0 0.0"; + powerOffColor = "0.0 0.0 0.0"; + targetTypeTag = 'ForceField'; + + texture[0] = "skins/forcef1"; + texture[1] = "skins/forcef2"; + texture[2] = "skins/forcef3"; + texture[3] = "skins/forcef4"; + texture[4] = "skins/forcef5"; + + framesPerSec = 10; + numFrames = 5; + scrollSpeed = 15; + umapping = 1.0; + vmapping = 0.15; +}; + + +function ForceFieldBare::onTrigger(%this, %triggerId, %on) +{ + // Default behavior for a field: + // if triggered: go to open state (last waypoint) + // if untriggered: go to closed state (first waypoint) + + if (%on == 1) { + %this.triggerCount++; + } else { + if (%this.triggerCount > 0) + %this.triggerCount--; + } + + if (%this.triggerCount > 0) { + %this.open(); + } else { + %this.close(); + } +} + +function ForceFieldBareData::gainPower(%data, %obj) { + Parent::gainPower(%data, %obj); + if (!shouldChangePowerState(%obj,true)) + return; + %obj.lastState = true; + if (%obj.realScale) { + %obj.setScale(%obj.realScale); + %obj.realScale = ""; + if (isObject(%obj.pzone)) + %obj.pzone.setTransform(%obj.getTransform()); + } + %obj.close(); + // activate the field's physical zone + if (isObject(%obj.pzone)) + %obj.pzone.activate(); +// %pzGroup = nameToID("MissionCleanup/PZones"); +// if(%pzGroup > 0) { +// %ffp = -1; +// for(%i = 0; %i < %pzGroup.getCount(); %i++) { +// %pz = %pzGroup.getObject(%i); +// if(%pz.ffield == %obj) { +// %ffp = %pz; +// break; +// } +// } +// if(%ffp > 0) { +// %ffp.activate(); + if( %data.getName() $= "defaultForceFieldBare" ) + killAllPlayersWithinZone( %data, %obj ); + else if( %data.getName() $= "defaultTeamSlowFieldBare" ) { + %team = %obj.team; + killAllPlayersWithinZone( %data, %obj, %team ); + } + else if (getSubStr(%data.getName(),0,18) $= "DeployedForceField") { + if (!%obj.notFirstPwr) { + %obj.notFirstPwr = true; + return; + } + else { + %team = %obj.team; + killAllPlayersWithinZone( %data, %obj, %team ); + } + } +// } + //else + // error("No PZones group to search!"); +} + +function killAllPlayersWithinZone( %data, %obj, %team ) { + %count = ClientGroup.getCount(); + for( %c = 0; %c < %count; %c++ ) { + %client = ClientGroup.getObject(%c); + if( isObject( %client.player ) ) { + if( %forceField = %client.player.isInForceField() ) { // isInForceField() will return the id of the ff or zero + if( %forceField == %obj ) { + %client.player.FFZapped = true; + %client.player.disableMove(true); + for( %i = 0; %i < 10; %i++ ) { + %client.player.schedule(%i * 200,play3d,ShockLanceHitSound); + schedule(%i * 200,0,playPain,%client.player); + %client.player.schedule(%i * 200,setActionThread,"Death" @ getRandom(10)+1); + } + %client.player.schedule(2000,blowup); // chunkOrama! + %client.player.schedule(2000,scriptkill,$DamageType::ForceFieldPowerup); + } + } + } + } +} + +function ForceFieldBareData::losePower(%data, %obj) { + Parent::losePower(%data, %obj); + if (!shouldChangePowerState(%obj,false)) + return; + %obj.lastState = false; + if (!%obj.realScale) { + %obj.realScale = %obj.getScale(); + %obj.setScale("0.01 0.01 0.01"); + if (isObject(%obj.pzone)) + %obj.pzone.setTransform(%obj.getTransform()); + } + %obj.open(); + // deactivate the field's physical zone + if (isObject(%obj.pzone)) + %obj.pzone.deactivate(); +// %pzGroup = nameToID("MissionCleanup/PZones"); +// if(%pzGroup > 0) { +// %ffp = -1; +// for(%i = 0; %i < %pzGroup.getCount(); %i++) { +// %pz = %pzGroup.getObject(%i); +// if(%pz.ffield == %obj) { +// %ffp = %pz; +// break; +// } +// } +// if(%ffp > 0) { +// %ffp.deactivate(); +// } +// } + //else + // error(""); +} + +function ForceFieldBareData::onAdd(%data, %obj) { + Parent::onAdd(%data, %obj); + + %velocityMod = 0.1; + %gravityMod = 1.0; + %appliedForce = "0 0 0"; + + if (%obj.velocityMod !$= "") + %velocityMod = %obj.velocityMod; + if (%obj.gravityMod !$= "") + %gravityMod = %obj.gravityMod; + if (%obj.appliedForce !$= "") + %appliedForce = %obj.appliedForce; + + %pz = new PhysicalZone() { + position = %obj.position; + rotation = %obj.rotation; + scale = %obj.scale; + polyhedron = "0.000000 1.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000 -1.0000000 0.0000000 0.0000000 0.0000000 1.0000000"; + velocityMod = %velocityMod; + gravityMod = %gravityMod; + appliedForce = %appliedForce; + ffield = %obj; + }; + + %obj.pzone = %pz; + + %pzGroup = nameToID("MissionCleanup/PZones"); + if(%pzGroup <= 0) { + %pzGroup = new SimGroup("PZones"); + MissionCleanup.add(%pzGroup); + } + %pzGroup.add(%pz); +} diff --git a/scripts/functions.cs b/scripts/functions.cs new file mode 100644 index 0000000..fc700f9 --- /dev/null +++ b/scripts/functions.cs @@ -0,0 +1,1034 @@ +// Universal handy function library collection, release 3.5 +// Created by DynaBlade +// All functions used here are made strictly by DynaBlade +// Functions made in the other attached files are made by their respective authors. + +// String Table +// + +$AllObjMask = $TypeMasks::PlayerObjectType | $TypeMasks::VehicleObjectType | $TypeMasks::StationObjectType | $TypeMasks::GeneratorObjectType | $TypeMasks::SensorObjectType | $TypeMasks::TurretObjectType | $TypeMasks::TerrainObjectType | $TypeMasks::InteriorObjectType | $TypeMasks::ForceFieldObjectType | $TypeMasks::StaticObjectType | $TypeMasks::MoveableObjectType | $TypeMasks::DamagableItemObjectType; +$DefaultLOSMask = $TypeMasks::TerrainObjectType | $TypeMasks::InteriorObjectType | $TypeMasks::StaticObjectType; +$CoreObjectMask = $TypeMasks::PlayerObjectType | $TypeMasks::VehicleObjectType | $TypeMasks::StationObjectType | $TypeMasks::GeneratorObjectType | $TypeMasks::SensorObjectType | $TypeMasks::TurretObjectType; +$EverythingMask = $notdone; + +// Datablock Cache +// + +datablock ShockLanceProjectileData(FXZap) +{ + directDamage = 0; + radiusDamageType = $DamageType::Default; + kickBackStrength = 0; + velInheritFactor = 0; + sound = ""; + + zapDuration = 1.0; + impulse = 0; + boltLength = 14.0; + extension = 14.0; // script variable indicating distance you can shock people from + lightningFreq = 50.0; + lightningDensity = 18.0; + lightningAmp = 0.25; + lightningWidth = 0.05; + + + boltSpeed[0] = 2.0; + boltSpeed[1] = -0.5; + + texWrap[0] = 1.5; + texWrap[1] = 1.5; + + startWidth[0] = 0.3; + endWidth[0] = 0.6; + startWidth[1] = 0.3; + endWidth[1] = 0.6; + + texture[0] = "special/shockLightning01"; + texture[1] = "special/shockLightning02"; + texture[2] = "special/shockLightning03"; + texture[3] = "special/ELFBeam"; +}; + +datablock ShockLanceProjectileData(FXPulse) +{ + directDamage = 0; + radiusDamageType = $DamageType::Default; + kickBackStrength = 0; + velInheritFactor = 0; + sound = ""; + + zapDuration = 1.0; + impulse = 0; + boltLength = 14.0; + extension = 14.0; // script variable indicating distance you can shock people from + lightningFreq = 50.0; + lightningDensity = 18.0; + lightningAmp = 0.25; + lightningWidth = 0.05; + + + boltSpeed[0] = 2.0; + boltSpeed[1] = -0.5; + + texWrap[0] = 1.5; + texWrap[1] = 1.5; + + startWidth[0] = 0.3; + endWidth[0] = 0.6; + startWidth[1] = 0.3; + endWidth[1] = 0.6; + + texture[0] = "special/nonlingradient"; + texture[1] = "special/nonlingradient"; + texture[2] = "special/nonlingradient"; + texture[3] = "special/nonlingradient"; +}; + +datablock ParticleData(TeleporterParticle) +{ + dragCoeffiecient = 0.0; + gravityCoefficient = -0.5; + inheritedVelFactor = 0.0; + + lifetimeMS = 100; + lifetimeVarianceMS = 50; + + textureName = "particleTest"; + + useInvAlpha = false; + spinRandomMin = -160.0; + spinRandomMax = 160.0; + + animateTexture = true; + framesPerSec = 15; + + + animTexName[0] = "special/Explosion/exp_0016"; + animTexName[1] = "special/Explosion/exp_0018"; + animTexName[2] = "special/Explosion/exp_0020"; + animTexName[3] = "special/Explosion/exp_0022"; + animTexName[4] = "special/Explosion/exp_0024"; + animTexName[5] = "special/Explosion/exp_0026"; + animTexName[6] = "special/Explosion/exp_0028"; + animTexName[7] = "special/Explosion/exp_0030"; + animTexName[8] = "special/Explosion/exp_0032"; + + colors[0] = "1 1 1 1"; + colors[1] = "0.75 0.75 1.0"; + colors[2] = "0.5 0.5 0.5 0.0"; + sizes[0] = 0.5; + sizes[1] = 1; + sizes[2] = 2.5; + times[0] = 0.0; + times[1] = 0.7; + times[2] = 1.0; +}; + +datablock ParticleEmitterData(TeleporterEmitter) +{ + ejectionPeriodMS = 3; + periodVarianceMS = 0; + ejectionVelocity = 6; + velocityVariance = 2.9; + ejectionOffset = 0.0; + thetaMin = 0; + thetaMax = 5; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + particles = "TeleporterParticle"; +}; + +datablock StaticShapeData(SlotExtension) +{ + shapeFile = "turret_muzzlepoint.dts"; +}; + +// ShapeBase/Parent calls +// + +function SimObject::getRotation(%obj) +{ + getRotation(%obj); +} + +function SimObject::getSlotRotation(%obj, %slot) +{ + getSlotRotation(%obj, %slot); +} + +function SimObject::getSlotPosition(%obj, %slot) +{ + getSlotPosition(%obj, %slot); +} + +function SimObject::isVehicle(%obj) +{ + isVehicle(%obj); +} + +function SimObject::isPlayer(%obj) +{ + isPlayer(%obj); +} + +function ShapeBase::zapObject(%obj) +{ + zapObject(%obj); +} + +function ShapeBase::zap2Object(%obj) +{ + zap2Object(%obj); +} + +function ShapeBase::stopZap(%obj) +{ + stopZap(%obj); +} + +function ShapeBase::applyKick(%obj, %force) +{ + applyKick(%obj, %force); +} + +function ShapeBase::useEnergy(%obj, %amount) +{ + useEnergy(%obj, %amount); +} + +function SimObject::setPosition(%obj, %pos) +{ + setPosition(%obj, %pos); +} + +function SimObject::setRotation(%obj, %rot) +{ + setRotation(%obj, %rot); +} + +function SimObject::play3D(%obj, %sound) +{ + play3D(%obj, %sound); +} + +function ShapeBase::teleportStartFX(%obj) +{ + teleportStartFX(%obj); +} + +function ShapeBase::teleportEndFX(%obj) +{ + teleportEndFX(%obj); +} + +function ShapeBase::getEyePoint(%obj) +{ + getEyePoint(%obj); +} + +function ShapeBase::getMuzzleRaycastPt(%obj, %slot, %dist) +{ + getMuzzleRaycastPt(%obj, %slot, %dist); +} + +function ShapeBase::getEyeRaycastPt(%obj, %dist) +{ + getEyeRaycastPt(%obj, %dist); +} + +function ShapeBase::getForwardRaycastPt(%obj, %dist) +{ + getForwardRaycastPt(%obj, %dist); +} + +function ShapeBase::getMass(%obj) +{ + getMass(%obj); +} + +function ShapeBase::getAccel(%obj) +{ + getAccel(%obj); +} + +function ShapeBase::getMaxEnergy(%obj) +{ + getMaxEnergy(%obj); +} + +function ShapeBase::getMaxDamage(%obj) +{ + getMaxDamage(%obj); +} + +function ShapeBase::getDamageLeft(%obj) +{ + getDamageLeft(%obj); +} + +function ShapeBase::getDamageLeftPct(%obj) +{ + getDamageLeftPct(%obj); +} + +function ShapeBase::getVelToForce(%obj) +{ + getVelToForce(%obj); +} + +function ShapeBase::getEnergyPct(%obj) +{ + getEnergyPct(%obj); +} + +function ShapeBase::getDamagePct(%obj) +{ + getDamagePct(%obj); +} + +function ShapeBase::getTransformAngle(%trans) +{ + getTransformAngle(%trans); +} + +function ShapeBase::createSlotExtension(%obj, %slot) +{ + createSlotExtension(%obj, %slot); +} + +function ShapeBase::deleteSlotExtension(%obj, %slot) +{ + deleteSlotExtension(%obj, %slot); +} + +// Function library +// + +function createSlotExtension(%obj, %slot) +{ + %ext = new StaticShape() + { + scale = "1 1 1"; + dataBlock = "SlotExtension"; + }; + %ext.isExtension = true; + + %obj.mountObject(%ext, %slot); + %obj.slotExtension[%slot] = %ext; + %obj.slotExtension[%slot].srcObj = %obj; +} + +function deleteSlotExtension(%obj, %slot) +{ + %ext = %obj.getMountNodeObject(%slot); + if(!%ext) + return; + + if(%ext.isExtension) + %ext.delete(); + + %obj.slotExtension[%slot] = ""; +} + + +function combineVars(%a, %b, %c) +{ + return %a SPC %b SPC %c; +} + +function posFrRaycast(%transform) +{ + %position = getWord(%transform, 1) @ " " @ getWord(%transform, 2) @ " " @ getWord(%transform, 3); + return %position; +} + +function normalFrRaycast(%transform) +{ + %norm = getWord(%transform, 4) @ " " @ getWord(%transform, 5) @ " " @ getWord(%transform, 6); + return %norm; +} + +function getEyePoint(%obj) +{ + %eyePt = getWords(%obj.getEyeTransform(), 0, 2); + return %eyePt; +} + +function play3D(%obj, %sound) +{ + serverPlay3D(%sound, %obj.getTransform()); +} + +function killit(%k) +{ + %k.delete(); +} + +function scanArea(%pos, %radius, %mask) +{ + InitContainerRadiusSearch(%pos, %radius, %mask); + while((%int = ContainerSearchNext()) != 0) + { + if(%int) + return true; + } + + return false; +} + +function testPosition(%obj) +{ + InitContainerRadiusSearch(%obj.getWorldBoxCenter(), 0.5, $DefaultLOSMask); + + while ((%test = ContainerSearchNext()) != 0) + { + if(%test) + return false; + else + return true; + } +} + +function createEmitter(%pos, %emitter, %rot) +{ + %dummy = new ParticleEmissionDummy() + { + position = %pos; + rotation = %rot; + scale = "1 1 1"; + dataBlock = defaultEmissionDummy; + emitter = %emitter; + velocity = "1"; + }; + MissionCleanup.add(%dummy); + %dummy.setRotation(%rot); + + if(isObject(%dummy)) + return %dummy; +} + +function createLifeEmitter(%pos, %emitter, %lifeMS, %rot) +{ + %dummy = createEmitter(%pos, %emitter, %rot); + schedule(%lifeMS, %dummy, "killit", %dummy); + return %dummy; +} + +function sqr(%num) +{ + return %num*%num; +} + +function cube(%num) +{ + return %num*%num*%num; +} + +function useEnergy(%obj, %amount) +{ + if(isObject(%obj)) + { + %energy = %obj.getEnergyLevel() - %amount; + %obj.setEnergyLevel(%energy); + } +} + +function modifyTransform(%trans1, %trans2) +{ + %tpx1 = getWord(%trans1, 0); + %tpy1 = getWord(%trans1, 1); + %tpz1 = getWord(%trans1, 2); + %tpa1 = getWord(%trans1, 3); + %tpb1 = getWord(%trans1, 4); + %tpc1 = getWord(%trans1, 5); + %tpd1 = getWord(%trans1, 6); + + %tpx2 = getWord(%trans2, 0); + %tpy2 = getWord(%trans2, 1); + %tpz2 = getWord(%trans2, 2); + %tpa2 = getWord(%trans2, 3); + %tpb2 = getWord(%trans2, 4); + %tpc2 = getWord(%trans2, 5); + %tpd2 = getWord(%trans2, 6); + + %trans = (%tpx1+%tpx2)@" "@(%tpy1+%tpy2)@" "@(%tpz1+%tpz2)@" "@(%tpa1+%tpa2)@" "@(%tpb1+%tpb2)@" "@(%tpc1+%tpc2)@" "@(%tpd1+%tpd2); + return %trans; +} + +function modifyTri(%trans1, %trans2) +{ + %tpx1 = getWord(%trans1, 0); + %tpy1 = getWord(%trans1, 1); + %tpz1 = getWord(%trans1, 2); + + %tpx2 = getWord(%trans2, 0); + %tpy2 = getWord(%trans2, 1); + %tpz2 = getWord(%trans2, 2); + + %tri = (%tpx1+%tpx2)@" "@(%tpy1+%tpy2)@" "@(%tpz1+%tpz2); + return %tri; +} + +function modifyQuad(%trans1, %trans2) // assuming for transform rotation +{ + %tpa1 = getWord(%trans1, 3); + %tpb1 = getWord(%trans1, 4); + %tpc1 = getWord(%trans1, 5); + %tpd1 = getWord(%trans1, 6); + + %tpa2 = getWord(%trans2, 3); + %tpb2 = getWord(%trans2, 4); + %tpc2 = getWord(%trans2, 5); + %tpd2 = getWord(%trans2, 6); + + %quad = (%tpa1+%tpa2)@" "@(%tpb1+%tpb2)@" "@(%tpc1+%tpc2)@" "@(%tpd1+%tpd2); + return %quad; +} + +function getTransformAngle(%trans) +{ + return getWord(%trans, 6); +} + +function setPosition(%obj, %pos) +{ + %rot = getWords(%obj.getTransform(), 3, 6); + %trans = %pos@" "@%rot; + %obj.setTransform(%trans); +} + +function setRotation(%obj, %rot) +{ + %pos = getWords(%obj.getTransform(), 0, 2); + %trans = %pos@" "@%rot; + %obj.setTransform(%trans); +} + +function getSlotPosition(%obj, %slot) +{ + return getWords(%obj.getSlotTransform(%slot), 0, 2); +} + +function getSlotRotation(%obj, %slot) +{ + return getWords(%obj.getSlotTransform(%slot), 3, 6); +} + +function getRotation(%obj) +{ + return getWords(%obj.getTransform(), 3, 6); +} + +function getRandomN(%max, %min) // negative getrandom +{ + if(%max !$= "" && %min !$= "") + return getRandom(%max, %min) * -1; + else if(%max !$= "") + return getRandom(%max) * -1; + else + return getRandom() * -1; +} + +function getRandomB() // boolean getRandom +{ + if(getRandom(1)) + return true; + else + return false; +} + +function getRandomT(%max, %min) +{ + if(%max !$= "" && %min !$= "") + return getRandomB() ? getRandom(%max, %min) : getRandomN(%max, %min); + else if(%max !$= "") + return getRandomB() ? getRandom(%max) : getRandomN(%max); + else + return getRandomB() ? getRandom() : getRandomN(); +} + +function shutdownServer(%time, %msg, %lines) +{ + %left = %time*1000; + centerPrintAll(%msg, %left, %lines); + schedule(%left, 0, "quit"); +} + +function velToSingle(%vel, %bool) // this function is also vectorLength :) +{ + %x = getWord(%vel, 0); + %y = getWord(%vel, 1); + %z = getWord(%vel, 2); + + if(%bool) + return mSqrt((%x*%x)+(%y*%y)+(%z*%z)); + else + return mFloor(mSqrt((%x*%x)+(%y*%y)+(%z*%z))); +} + +function MStoKPH(%vel, %bool) // for more accurate conversions +{ + if(%bool) + return %vel * 3.6; + else + return mFloor(%vel * 3.6); +} + +function KPHtoMPH(%vel, %bool) +{ + if(%bool) + return %vel * 0.6214; + else + return mFloor(%vel * 0.6214); +} + +function vectorNeg(%vec) +{ + %v1 = getWord(%vec, 0) * -1; + %v2 = getWord(%vec, 1) * -1; + %v3 = getWord(%vec, 2) * -1; + return %v1@" "@%v2@" "@%v3; +} + +function vectorRandom() +{ + return getRandomT()@" "@getRandomT()@" "@getRandomT(); +} + +function vectorClear(%vec) // for you lazy types +{ + return "0 0 0"; +} + +function vectorCopy(%veca, %vecb) // also for you lazy types +{ + %vecb = getWords(%veca, 0, 2); + return; +} + +function vectorCompare(%va, %vb) +{ + %v1[0] = getWord(%va, 0); + %v1[1] = getWord(%va, 1); + %v1[2] = getWord(%va, 2); + + %v2[0] = getWord(%vb, 0); + %v2[1] = getWord(%vb, 1); + %v2[2] = getWord(%vb, 2); + + if(%v1[0] != %v2[0] || %v1[1] != %v2[1] || %v1[2] != %v2[2]) + return 0; + + return 1; +} + +function vectorToRotZ(%vec) // only for Z rotations +{ + %radian = mAcos(getWord(%vec, 1)); + %angle = (%radian / 0.0175); + %newrot = " 0 0 1 " @ (270 - %angle); + return %newrot; +} + +function getLOSOffset(%obj, %vec, %dist) +{ + %pos = %obj.getPosition(); + %dir = vectorNormalize(%vec); + %nvec = vectorScale(%dir, %dist); + return vectorAdd(%pos, %nvec); +} + +function S_vectorNormalize(%vec) // Source code on vectorNormalize +{ + %length = 0; + %ilength = 0; + %v[0] = getWord(%vec, 0); + %v[1] = getWord(%vec, 1); + %v[2] = getWord(%vec, 2); + + %length = mSqrt((%v[0]*%v[0]) + (%v[1]*%v[1]) + (%v[2]*%v[2])); + + if(%length) // no division by 0 thx :) + { + %ilength = 1/%length; + %v[0] *= %ilength; + %v[1] *= %ilength; + %v[2] *= %ilength; + } + + %nVec = combineVars(%v[0], %v[1], %v[2]); + return %nVec; +} + +function getDistance2D(%a, %b) +{ + %x1 = getWord(%a, 0); + %y1 = getWord(%b, 0); + %x2 = getWord(%a, 1); + %y2 = getWord(%b, 1); + + %dist = mSqrt(sqr(%x2 - %x1) + sqr(%y2 - %y1)); + return %dist; +} + +function getObjectDistance(%obj1, %obj2) +{ + %obj1b = %obj1.getWorldBoxCenter(); + %obj2b = %obj2.getWorldBoxCenter(); + + %tpx1 = getWord(%obj1b, 0); + %tpy1 = getWord(%obj1b, 1); + %tpz1 = getWord(%obj1b, 2); + + %tpx2 = getWord(%obj2b, 0); + %tpy2 = getWord(%obj2b, 1); + %tpz2 = getWord(%obj2b, 2); + + %dist = mSqrt(sqr(%tpx2 - %tpx1) + sqr(%tpy2 - %tpy1) + sqr(%tpz2 - %tpz1)); + return %dist; +} + +function getVectorFromPoints(%pt1, %pt2) +{ + return VectorNormalize(VectorSub(%pt2, %pt1)); +} + +function getVectorFromObjects(%obj1, %obj2) +{ + %obj1b = %obj1.getWorldBoxCenter(); + %obj2b = %obj2.getWorldBoxCenter(); + + return VectorNormalize(VectorSub(%obj2b, %obj1b)); +} + +function isWithinVariance(%va, %vb, %variance) // vector 1, vector 2, variant percentage out of 100% ex (0.9*360 / 360) +{ + %dot = vectorDot(vectorNormalize(%va), vectorNormalize(%vb)); + if(%dot >= %variance/360) + return true; + else + return false; +} + +function getDistance3D(%ptA, %ptB) +{ + %tpx1 = getWord(%ptA, 0); + %tpy1 = getWord(%ptA, 1); + %tpz1 = getWord(%ptA, 2); + + %tpx2 = getWord(%ptB, 0); + %tpy2 = getWord(%ptB, 1); + %tpz2 = getWord(%ptB, 2); + + %dist = mSqrt(sqr(%tpx2 - %tpx1) + sqr(%tpy2 - %tpy1) + sqr(%tpz2 - %tpz1)); + return %dist; +} + +function zapObject(%obj) +{ + %obj.zap = new ShockLanceProjectile() + { + dataBlock = "fxzap"; + initialDirection = "0 0 0"; + initialPosition = %obj.getWorldBoxCenter(); + sourceObject = %obj; + sourceSlot = 0; + targetId = %obj; + }; + MissionCleanup.add(%obj.zap); +} + +function zap2Object(%obj) +{ + %obj.zap = new ShockLanceProjectile() + { + dataBlock = "fxpulse"; + initialDirection = "0 0 0"; + initialPosition = %obj.getWorldBoxCenter(); + sourceObject = %obj; + sourceSlot = 0; + targetId = %obj; + }; + MissionCleanup.add(%obj.zap); +} + +function stopZap(%obj) +{ + if(isObject(%obj)) + { + if(isObject(%obj.zap)) + %obj.zap.delete(); + } +} + +function teleportStartFX(%obj) +{ + if(%obj.holdingFlag) + { + %client = %obj.client; + %flag = %obj.holdingFlag; + %flag.setVelocity("0 0 0"); + %flag.setTransform(%obj.getWorldBoxCenter()); + %flag.setCollisionTimeout(%obj); + %obj.throwObject(%flag); + messageClient(%obj.client, 'MsgNoTeleFlag', '\c1You cannot teleport with the flag.'); + } + + %obj.playShieldEffect("0 0 1"); + %obj.setCloaked(true); + %obj.startFade( 1000, 0, true ); + %obj.play3D(TeleportSound); + + %particles = createEmitter(%obj.getPosition(), "TeleporterEmitter"); + schedule(2500, 0, "killit", %particles); +} + +function teleportEndFX(%obj) +{ + %obj.setCloaked(false); + %obj.playShieldEffect("0 0 1"); + %obj.startFade(1000, 0, false ); + %obj.play3D(UnTeleportSound); + if (isObject(%obj.particleFX)) + %obj.particleFX.delete(); + + %particles = createEmitter(%obj.getPosition(), "TeleporterEmitter"); + schedule(2500, 0, "killit", %particles); +} + +function getMuzzleRaycastPt(%obj, %slot, %dist) +{ + %vec = %obj.getMuzzleVector(%slot); + %pos = %obj.getMuzzlePoint(%slot); + %nVec = VectorNormalize(%vec); + %scVec = VectorScale(%nVec, %dist); + %end = VectorAdd(%pos, %scVec); + %searchResult = containerRayCast(%pos, %end, $TypeMasks::TerrainObjectType | $TypeMasks::InteriorObjectType | $TypeMasks::PlayerObjectType | $TypeMasks::VehicleObjectType | $TypeMasks::StaticShapeObjectType | $TypeMasks::TurretObjectType | $TypeMasks::ItemObjectType, 0); + %raycastPt = posFrRaycast(%searchResult); + %raycastPt.raycast = %searchResult; + + return %raycastPt; +} + +function getEyeRaycastPt(%obj, %dist) +{ + %vec = %obj.getEyeVector(); + %pos = %obj.getEyePoint(); + %nVec = VectorNormalize(%vec); + %scVec = VectorScale(%nVec, %dist); + %end = VectorAdd(%pos, %scVec); + %searchResult = containerRayCast(%pos, %end, $TypeMasks::TerrainObjectType | $TypeMasks::InteriorObjectType | $TypeMasks::PlayerObjectType | $TypeMasks::VehicleObjectType | $TypeMasks::StaticShapeObjectType | $TypeMasks::TurretObjectType | $TypeMasks::ItemObjectType, 0); + %raycastPt = posFrRaycast(%searchResult); + %raycastPt.raycast = %searchResult; + + return %raycastPt; +} + +function getForwardRaycastPt(%obj, %dist) +{ + %vec = %obj.getForwardVector(); + %pos = %obj.getWorldBoxCenter(); + %nVec = VectorNormalize(%vec); + %scVec = VectorScale(%nVec, %dist); + %end = VectorAdd(%pos, %scVec); + %searchResult = containerRayCast(%pos, %end, $TypeMasks::TerrainObjectType | $TypeMasks::InteriorObjectType | $TypeMasks::PlayerObjectType | $TypeMasks::VehicleObjectType | $TypeMasks::StaticShapeObjectType | $TypeMasks::TurretObjectType | $TypeMasks::ItemObjectType, 0); + %raycastPt = posFrRaycast(%searchResult); + %raycastPt.raycast = %searchResult; + + return %raycastPt; +} + +function applyKick(%obj, %force) +{ + %vec = VectorScale(%obj.getMuzzleVector(0), %force); + %obj.applyImpulse(%obj.getTransform(), %vec); +} + +function getMass(%obj) +{ + return %obj.getDatablock().mass; +} + +function getMaxEnergy(%obj) +{ + return %obj.getDatablock().maxEnergy; +} + +function getMaxDamage(%obj) +{ + return %obj.getDatablock().maxDamage; +} + +function getEnergyPct(%obj) +{ + return %obj.getEnergyLevel() / %obj.getMaxEnergy(); +} + +function getDamagePct(%obj) +{ + return %obj.getDamageLevel() / %obj.getMaxDamage(); +} + +function getDamageLeft(%obj) +{ + return %obj.getMaxDamage() - %obj.getDamageLevel(); +} + +function getDamageLeftPct(%obj) +{ + return %obj.getDamageLeft() / %obj.getMaxDamage(); +} + +function getAccel(%obj) +{ + %vel = vectorScale(%obj.getVelocity(), 0.01); + schedule(1, 0, "returnAccel", %obj, %vel); +} + +function returnAccel(%obj, %vel1) +{ + %vel = vectorScale(%obj.getVelocity(), 0.01); + return vectorScale(vectorSub(%vel, %vel1), 0.01); // a = dv/dt +} + +function getVelToForce(%obj) +{ + %accel = %obj.getAccel(); + %mass = %obj.getMass(); + return vectorScale(%accel, %mass); +} + +function getTowForce(%obj, %target) +{ + %accel = %obj.getAccel(); + %mass = %target.getMass(); + return vectorScale(%accel, %mass); +} + +function setFlightCeiling(%val) +{ + %missionArea = nameToID("MissionGroup/MissionArea"); + + if(%missionArea != -1) + %missionArea.FlightCeiling = %val; +} + +function reload(%script) +{ + compile(%script); // Added by JackTL - Duh!! + exec(%script); + %count = ClientGroup.getCount(); + + for(%i = 0; %i < %count; %i++) + { + %cl = ClientGroup.getObject(%i); + + if(!%cl.isAIControlled()) // no sending bots datablocks.. LOL + %cl.transmitDataBlocks(0); // all clients on server + } +} + +function isVehicle(%obj) +{ + if(isObject(%obj)) + { + %data = %obj.getDataBlock(); + %className = %data.className; + + if(%className $= WheeledVehicleData || %className $= FlyingVehicleData || %className $= HoverVehicleData) + return true; + else + return false; + } +} + +function isPlayer(%obj) +{ + if(isObject(%obj)) + { + %data = %obj.getDataBlock(); + %className = %data.className; + + if(%className $= Armor) + return true; + else + return false; + } +} + +function changeServerHostname(%name) +{ + $Host::GameName = %name; +} + +function changeServerAllowAliases(%bool) +{ + $Host::NoSmurfs = %bool; +} + +function changeServerPlayerCount(%num) +{ + $Host::MaxPlayers = %num; +} + +function changeAdminPassword(%pass) +{ + if(%pass) + $Host::AdminPassword = %pass; + else + $Host::AdminPassword = ""; +} + +function changeServerPassword(%pass) +{ + if(%pass) + $Host::Password = %pass; + else + $Host::Password = ""; +} + +function setServerPrefs(%name, %aliases, %admin, %password, %num) +{ + $Host::CRCTextures = 0; + if(%name !$= "") + changeServerHostname(%name); + if(%aliases !$= "") + changeServerAllowAliases(%aliases); + if(%num !$= "") + changeServerPlayerCount(%num); + + changeAdminPassword(%admin); + changeServerPassword(%password); +} + +function hasDecimal(%num) +{ +if (mFloor(%num) != %num) +{ +return true; +} +else { +return false; +} +} + +function findPrimes(%num) +{ +%dividebythis = 1; +%dividend = 1; +while (%dividend < %num) +{ +while (%dividebythis < %dividend) +{ +if (hasDecimal(%dividend/%dividebythis) == false) +{ +echo(%dividend); +} +else { +//nothing +} +%dividebythis++; +} +} +} diff --git a/scripts/gameBase.cs b/scripts/gameBase.cs new file mode 100644 index 0000000..18c73d7 --- /dev/null +++ b/scripts/gameBase.cs @@ -0,0 +1,147 @@ + +function GameBaseData::onAdd(%data, %obj) +{ + if(%data.targetTypeTag !$= "") + { + // use the name given to the object in the mission file + if(%obj.nameTag !$= "") + { + %obj.nameTag = addTaggedString(%obj.nameTag); + %nameTag = %obj.nameTag; + } + else + %nameTag = %data.targetNameTag; + + %obj.target = createTarget(%obj, %nameTag, "", "", %data.targetTypeTag, 0, 0); + } + else + %obj.target = -1; +} + +function GameBaseData::onRemove(%data, %obj) +{ + %target = %obj.getTarget(); + + // first 32 targets are team targets + if(%target >= 32) + { + if(%obj.nameTag !$= "") + removeTaggedString(%obj.nameTag); + freeTarget(%target); + } +} + +function InteriorInstance::damage() +{ +} + +function TerrainBlock::damage() +{ +} + +function WaterBlock::damage() { +} + +function ForceFieldBare::damage(%this, %sourceObject, %position, %amount, %damageType) { + %this.getDataBlock().damageObject(%this, %sourceObject, %position, %amount, %damageType); +} + +function ForceFieldBareData::damageObject(%data, %targetObject, %sourceObject, %position, %amount, %damageType) { + StaticShapeData::damageObject(%data, %targetObject, %sourceObject, %position, %amount, %damageType); +} + +function ForceFieldBare::applyDamage(%obj,%amount,%sourceObject,%position,%damageType) { + %dataBlockName = %obj.getDataBlock().getName(); + if (getSubStr(%dataBlockName,0,18) $= "DeployedForceField" || getSubStr(%dataBlockName,0,20) $= "DeployedGravityField") { + %count = getWordCount($PowerList); + for(%i=0;%i<%count;%i++) { + %powerObj = getWord($PowerList,%i); + if (genPoweringObj(%powerObj,%obj)) + %powerList = %powerList SPC %powerObj; + } + %powerList = trim(%powerList); + %genDamage = (%amount * 1) / getWordCount(%powerList); + %count = getWordCount(%powerList); + for(%i=0;%i<%count;%i++) { + %powerObj = getWord(%powerList,%i); + %mult = (1 - 0.05) + (getRandom() * 0.10); + %powerObj.damage(%sourceObject,%position,%genDamage * %mult,%damageType); + } + } +} + +function ForceFieldBare::isEnabled() { + // created to prevent console errors +} + +function GameBaseData::shouldApplyImpulse(%data, %obj) +{ + return %data.shouldApplyImpulse; +} + + +function ShapeBaseData::onAdd(%data, %obj) +{ + Parent::onAdd(%data, %obj); + // if it's a deployed object, schedule the ambient thread to play in a little while + if(%data.deployAmbientThread) + %obj.schedule(750, "playThread", $AmbientThread, "ambient"); + // check for ambient animation that should always be played + if(%data.alwaysAmbient) + %obj.playThread($AmbientThread, "ambient"); +} + +function SimObject::setOwnerClient(%obj, %cl) +{ + %obj.client = %cl; +} + +function SimObject::getOwnerClient(%obj) +{ + if(isObject(%obj)) + return %obj.client; + return 0; +} + // recursive objective init functions for mission group + +function SimGroup::objectiveInit(%this) +{ + for (%i = 0; %i < %this.getCount(); %i++) + %this.getObject(%i).objectiveInit(); +} + +function SimObject::objectiveInit(%this) +{ +} + +function GameBase::objectiveInit(%this) +{ + //error("Initializing object " @ %this @ ", " @ %this.getDataBlock().getName()); + %this.getDataBlock().objectiveInit(%this); +} + +// tag strings are ignored if they start with an underscore +function GameBase::getGameName(%this) +{ + %name = ""; + + if(%this.nameTag !$= "") + %name = %this.nameTag; + else + { + %name = getTaggedString(%this.getDataBlock().targetNameTag); + if((%name !$= "") && (getSubStr(%name, 0, 1) $= "_")) + %name = ""; + } + + %type = getTaggedString(%this.getDataBlock().targetTypeTag); + if((%type !$= "") && (getSubStr(%type, 0, 1) !$= "_")) + { + if(%name !$= "") + return(%name @ " " @ %type); + else + return(%type); + } + + return(%name); +} diff --git a/scripts/hazard.cs b/scripts/hazard.cs new file mode 100644 index 0000000..56c2276 --- /dev/null +++ b/scripts/hazard.cs @@ -0,0 +1,134 @@ +// hazard.cs + +if ($Host::Hazard::Enabled $= "") + $Host::Hazard::Enabled = 0; // Disable as default +if ($Hazard::HazardTimer < 500) + $Hazard::HazardTimer = 2500; // Hazard loop timer +if ($Hazard::StormTimer < 100) + $Hazard::StormTimer = 500; // Hazard "storm" loop timer +if ($Hazard::HazardStormDurationMin $= "") + $Hazard::HazardStormDurationMin = 20000; // Storm duration min +if ($Hazard::HazardStormDurationMax $= "") + $Hazard::HazardStormDurationMax = 60000; // Storm duration max +if ($Hazard::StormRandom $= "") + $Hazard::StormRandom = 120; // Storm random chance +if ($Hazard::MeteorMax < 1) + $Hazard::MeteorMax = 1; // Max meteors per run +if ($Hazard::MeteorMin $= "" || $Hazard::MeteorMin > $Hazard::MeteorMax) + $Hazard::MeteorMin = 0; // Min meteors per run +if ($Hazard::MeteorRad $= "") + $Hazard::MeteorRad = 100; // Meteor drop radius + +if ($Hazard::MaxSlant < 0 || $Hazard::MaxSlant $= "") + $Hazard::MaxSlant = 0.4; +if ($Hazard::BDropAddX $= "") + $Hazard::BDropAddX = 0.00153; +if ($Hazard::BDropAddY $= "") + $Hazard::BDropAddY = 0.00956; +if ($Hazard::DropAddVariation $= "") + $Hazard::DropAddVariation = 0.0010; // divided by two = +/- 0.0005 +if ($Hazard::DropAddVariationTime < 1) + $Hazard::DropAddVariationTime = 1000 * 60 * 10; // 10 minutes + +if ($Hazard::DropX $= "" || mAbs($Hazard::DropX) > 1) + $Hazard::DropX = (getRandom() * 2) - 1; +if ($Hazard::DropY $= "" || mAbs($Hazard::DropY) > 1) + $Hazard::DropY = 0; + + +function hazardOn() { + $Host::Hazard::Enabled = 1; + hazardThread($Hazard::HazardThread++); +} + +function hazardOff() { + $Host::Hazard::Enabled = 0; +} + +function hazardThread(%thread) { + if (%thread != $Hazard::HazardThread || $Host::Hazard::Enabled != 1 || !isObject(MissionCleanup)) { + warn("HazardThread #" @ mAbs(%thread) @ " stopped. Last started thread: " @ $Hazard::HazardThread); + return; + } + + if ($Hazard::StormTime $= "") { + %rnd = getRandom(0,$Hazard::StormRandom); + if (%rnd == 1) { + // With default values, warning is 10 to 40 sec prior to storm + $Hazard::StormTime = getSimTime() + ($Hazard::HazardTimer * 4) + ($Hazard::HazardTimer * getRandom(0,12)); + $Hazard::HazardStormDuration = getRandom($Hazard::HazardStormDurationMin,$Hazard::HazardStormDurationMax); + messageAll('msgClient','\c2Warning: Meteor storm expected in %1 seconds!~wfx/misc/warning_beep.wav',mFloor(($Hazard::StormTime - getSimTime()) / 1000)); + $Hazard::StormTime = $Hazard::StormTime - 10; // fix + } + } + else { + if ($Hazard::StormTime < getSimTime() && $Hazard::StormActive != true) { + $Hazard::StormTime = getSimTime(); + $Hazard::StormActive = true; + messageAll('msgClient','\c2Warning: Meteor storm imminent!~wfx/misc/red_alert.wav'); + messageAll('msgClient','~wvoice/Training/Any/ANY.prompt0%1.WAV',getRandom(1,7)); + } + if ($Hazard::StormTime + $Hazard::HazardStormDuration < getSimTime()) { + $Hazard::StormActive = false; + $Hazard::StormTime = ""; + messageAll('msgClient','\c2Meteor storm passing.'); + } + } + + if ($Hazard::DropAddX $= "") + $Hazard::DropAddX = $Hazard::BDropAddX; + if ($Hazard::DropAddY $= "") + $Hazard::DropAddY = $Hazard::BDropAddY; + if ($Hazard::DropAddVariationLastTime $= "") // Don't randomize on first run + $Hazard::DropAddVariationLastTime = getSimTime(); + + if ($Hazard::DropAddVariationLastTime + $Hazard::DropAddVariationTime < getSimTime()) { + $Hazard::DropAddVariationLastTime = getSimTime(); + $Hazard::DropAddX = $Hazard::BDropAddX + ((getRandom() * $Hazard::DropAddVariation) - ($Hazard::DropAddVariation / 2)); + $Hazard::DropAddY = $Hazard::BDropAddY + ((getRandom() * $Hazard::DropAddVariation) - ($Hazard::DropAddVariation / 2)); + } + + $Hazard::DropX = $Hazard::DropX + $Hazard::DropAddX; + $Hazard::DropY = $Hazard::DropY + $Hazard::DropAddY; + + if (mAbs($Hazard::DropX) > 1) { + $Hazard::DropX = 1 * lev($Hazard::DropX); + $Hazard::DropAddX = -$Hazard::DropAddX; + } + + if (mAbs($Hazard::DropY) > 1) { + $Hazard::DropY = 1 * lev($Hazard::DropY); + $Hazard::DropAddY = -$Hazard::DropAddY; + } + + %x = mCos(($Hazard::DropX * $Pi) + $Pi) * mSin(($Hazard::DropY * ($Pi / 2) + ($Pi / 2)) * $Hazard::MaxSlant); + %y = mSin(($Hazard::DropX * $Pi) + $Pi) * mSin(($Hazard::DropY * ($Pi / 2) + ($Pi / 2)) * $Hazard::MaxSlant); + %z = mCos(($Hazard::DropY * ($Pi / 2) + ($Pi / 2)) * $Hazard::MaxSlant); + %dropVec = vectorScale(%x SPC %y SPC -%z,5); + + // Meteors + // Players + %count = ClientGroup.getCount(); + for(%i = 0; %i < %count; %i++) { + %cl = ClientGroup.getObject(%i); + if (isObject(%cl.player) && !%cl.isJailed) { + %num = getRandom($Hazard::MeteorMin,$Hazard::MeteorMax); + if (%num > 0) + JTLMeteorStorm(%cl,0,$Hazard::MeteorRad,%num,400,600,0,0,0,0,0,0,vectorScale(%dropVec,0.975 + (getRandom() * 0.05)),1); + } + } + // Generators + %count = getWordCount($PowerList); + for(%i = 0; %i < %count; %i++) { + %obj = getWord($PowerList,%i); + if (isObject(%obj)) { + %num = getRandom($Hazard::MeteorMin,$Hazard::MeteorMax); + if (%num > 0) + JTLMeteorStorm(%obj,0,$Hazard::MeteorRad,%num,400,600,0,0,0,0,0,0,vectorScale(%dropVec,0.975 + (getRandom() * 0.05)),1); + } + } + if ($Hazard::StormActive == true) + schedule($Hazard::StormTimer,0,HazardThread,%thread); + else + schedule($Hazard::HazardTimer,0,HazardThread,%thread); +} diff --git a/scripts/hfunctions.cs b/scripts/hfunctions.cs new file mode 100644 index 0000000..b24dd6d --- /dev/null +++ b/scripts/hfunctions.cs @@ -0,0 +1,106 @@ +function LightningStrike(%client,%delay) { + if (%client.player) + %pos = %client.player.getTransform(); + %one = getword(%pos, 0) SPC getword(%pos, 1) SPC getword(%pos, 2); + %player = %client.player; + %b = new StaticShape() { + position = %pos; + datablock = "LightningTarget"; + }; + schedule(%delay, 0, "actualstrike", %b); +} + +function actualstrike(%obj) { + %posr = %obj.getTransform(); + %pos = VectorAdd(%posr, "0 0 -20"); + %pos2 = VectorAdd(%posr, "0 0 -20"); + for (%i=0;%i<10;%i++) { + %pos = VectorAdd(%pos, "0 0 20"); + %p[%i] = new Lightning() { + scale = "1 1 1"; + position = %pos; + rotation = "1 0 0 0"; + dataBlock = "DefaultStorm"; + strikesPerMinute = "120"; + strikeWidth = "1.0"; + chanceToHitTarget = "1.0"; + strikeRadius = "1"; + boltStartRadius = "10"; + color = "1.000000 1.000000 1.000000 1.000000"; + fadeColor = "0.300000 0.300000 1.000000 1.000000"; + useFog = "1"; + }; + %p[%i].schedule(1500, "delete"); + %p[%i].strikeObject(%player); + } + schedule(1000, 0, "LightningApplyDamage", %p, %pos, %pos2); + if (%obj) + %obj.schedule(1500, "delete"); +} + +function LightningWeaponImage::onFire(%data, %obj, %slot) { + %range = 1000; + %rot = getWords(%obj.getTransform(), 3, 6); + %muzzlePos = %obj.getMuzzlePoint(%slot); + %muzzleVec = %obj.getMuzzleVector(%slot); + %endPos = VectorAdd(%muzzlePos, VectorScale(%muzzleVec, %range)); + %damageMasks = $TypeMasks::PlayerObjectType | $TypeMasks::VehicleObjectType | + $TypeMasks::StationObjectType | $TypeMasks::GeneratorObjectType | + $TypeMasks::SensorObjectType | $TypeMasks::TurretObjectType | + $TypeMasks::TerrainObjectType; //|$TypeMasks::InteriorObjectType; + %hit = ContainerRayCast(%muzzlePos, %endPos, %damageMasks, %obj); + if (%hit) { + %posr = getWords(%hit, 1, 3); + %pos = VectorAdd(%posr, "0 0 300"); + %pos2 = VectorAdd(%posr, "0 0 -20"); + %b = new StaticShape() { + position = %pos2; + datablock = "LightningTarget"; + }; + %p = new Lightning() { + scale = "1 1 1"; + position = %pos; + rotation = "1 0 0 0"; + dataBlock = "DefaultStorm"; + strikesPerMinute = "120"; + strikeWidth = "10.0"; + chanceToHitTarget = "1"; + strikeRadius = "10"; + boltStartRadius = "15"; + color = "1.000000 1.000000 1.000000 1.000000"; + fadeColor = "0.300000 0.300000 1.000000 1.000000"; + useFog = "1"; + sourceObject = %obj; + sourceSlot = %slot; + vehicleObject = 0; + }; + %p.strikeObject(%b); + schedule(1000, 0, "LightningApplyDamage", %p, %pos, %pos2); + %p.schedule(1500, "delete"); + %b.schedule(1500, "delete"); + } +} + +function LightningApplyDamage(%p, %pos, %pos2) { + %damageMasks = $TypeMasks::TerrainObjectType | $TypeMasks::InteriorObjectType; + %hit = ContainerRayCast(%pos, %pos2, %damageMasks, 1); + if (%hit) + %pos2 = getWords(%hit, 1, 3); + %xy = getWords(%pos, 0, 1); + %z1 = getWord(%pos, 2) - 5; + %z2 = getWord(%pos2, 2) + 5; + while (%z1 > %z2) { + %pos = %xy SPC %z1; + RadiusExplosion(%p, %pos, 40, 0.4, 0, %p.sourceObject, $DamageType::Lightning); + %z1 -= 19; + } + %pos = %xy SPC %z1; + RadiusExplosion(%p, %pos, 40, 0.4, 0, %p.sourceObject, $DamageType::Lightning); +} + +datablock StaticShapeData(LightningTarget) { + shapeFile = "turret_muzzlepoint.dts"; + targetNameTag = 'beacon'; + isInvincible = true; + dynamicType = $TypeMasks::StaticObjectType; +}; diff --git a/scripts/hud.cs b/scripts/hud.cs new file mode 100644 index 0000000..c2e9b44 --- /dev/null +++ b/scripts/hud.cs @@ -0,0 +1,1929 @@ +//-------------------------------------------------------------------------- +function GameConnection::sensorPing(%this, %ping) +{ + sensorHud.ping = %ping; + sensorHud.update(); +} + +function GameConnection::sensorJammed(%this, %jam) +{ + sensorHud.jam = %jam; + sensorHud.update(); +} + +function SensorHud::update(%this) +{ + if(!%this.ping && !%this.jam) + { + %this.setVisible(false); + sensorHudBack.setVisible(true); + return; + } + + %this.setVisible(true); + sensorHudBack.setVisible(false); + + if(%this.jam) + %this.color = %this.jamColor; + else + %this.color = %this.pingColor; +} + +// - anything which should be reset on new server/mission +function clientCmdResetHud() +{ + deploySensor.setVisible(false); + controlObjectText.setVisible(false); + + sensorHud.jam = false; + sensorHud.ping = false; + sensorHud.update(); +} + +//-------------------------------------------------------------------------- +$vehicleReticle[AssaultVehicle, 1, bitmap] = "gui/hud_ret_tankchaingun"; +$vehicleReticle[AssaultVehicle, 1, frame] = true; +$vehicleReticle[AssaultVehicle, 2, bitmap] = "gui/hud_ret_tankmortar"; +$vehicleReticle[AssaultVehicle, 2, frame] = true; + +$vehicleReticle[BomberFlyer, 1, bitmap] = "gui/hud_ret_shrike"; +$vehicleReticle[BomberFlyer, 1, frame] = false; +$vehicleReticle[BomberFlyer, 2, bitmap] = ""; +$vehicleReticle[BomberFlyer, 2, frame] = false; +$vehicleReticle[BomberFlyer, 3, bitmap] = "gui/hud_ret_targlaser"; +$vehicleReticle[BomberFlyer, 3, frame] = false; + +function GameConnection::setVWeaponsHudActive(%client, %slot) +{ + %veh = %client.player.getObjectMount(); + %vehType = %veh.getDatablock().getName(); + commandToClient(%client, 'setVWeaponsHudActive', %slot, %vehType); +} + +function clientCmdSetVWeaponsHudActive(%num, %vType) +{ + //vWeaponsBox.setActiveWeapon(%num); + if(%num > $numVWeapons) + %num = $numVWeapons; + + for(%i = 1; %i <= $numVWeapons; %i++) + { + %oldHilite = "vWeap" @ %i @ "Hilite"; + %oldHilite.setVisible(false); + } + %newHilite = "vWeap" @ %num @ "Hilite"; + %newHilite.setVisible(true); + + // set the bitmap and frame for the reticle + reticleHud.setBitmap($vehicleReticle[%vType, %num, bitmap]); + reticleFrameHud.setVisible($vehicleReticle[%vType, %num, frame]); +} + +function GameConnection::setVWeaponsHudClearAll(%client) +{ + commandToClient(%client, 'setVWeaponsHudClearAll'); +} + +function clientCmdSetVWeaponsHudClearAll() +{ + //vWeaponsBox.clearAll(); +} + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +function GameConnection::setWeaponsHudBitmap(%client, %slot, %name, %bitmap) +{ + commandToClient(%client, 'setWeaponsHudBitmap',%slot,%name,%bitmap); +} + +//---------------------------------------------------------------------------- +function clientCmdSetWeaponsHudBitmap(%slot, %name, %bitmap) +{ + $WeaponNames[%slot] = %name; + weaponsHud.setWeaponBitmap(%slot,%bitmap); +} + +//---------------------------------------------------------------------------- +function GameConnection::setWeaponsHudItem(%client, %name, %ammoAmount, %addItem) +{ + //error("GC:SWHI name="@%name@",ammoAmount="@%ammoAmount@",addItem="@%addItem); +// for(%i = 0; %i < $WeaponsHudCount; %i++) +// if($WeaponsHudData[%i, itemDataName] $= %name) +// { +// if($WeaponsHudData[%i, ammoDataName] !$= "") { +// %ammoInv = %client.player.inv[$WeaponsHudData[%i, ammoDataName]]; +// //error(" ----- player has " @ %ammoInv SPC $WeaponsHudData[%i, ammoDataName]); +// //error("SWHI:Setting weapon "@%name@" ("@%i@") ammo to " @ %ammoInv); +// commandToClient(%client, 'setWeaponsHudItem',%i,%ammoInv, %addItem); +// } +// else { +// //error("SWHI:Setting weapon "@%name@" ("@%i@") ammo to infinite"); +// commandToClient(%client, 'setWeaponsHudItem',%i,-1, %addItem); +// } +// break; +// } + + + // My try... + for(%i = 0; %i < $WeaponsHudCount; %i++) + if($WeaponsHudData[%i, itemDataName] $= %name) + { + if($WeaponsHudData[%i, ammoDataName] !$= "") { + %ammoInv = %client.player.inv[$WeaponsHudData[%i, ammoDataName]]; + //error(" ----- player has " @ %ammoInv SPC $WeaponsHudData[%i, ammoDataName]); + //error("SWHI:Setting weapon "@%name@" ("@%i@") ammo to " @ %ammoInv); + commandToClient(%client, 'setWeaponsHudItem',%i,%ammoInv, %addItem); + } + else { + //error("SWHI:Setting weapon "@%name@" ("@%i@") ammo to infinite"); + commandToClient(%client, 'setWeaponsHudItem',%i,-1, %addItem); + } + break; + } +} + +//---------------------------------------------------------------------------- +function clientCmdSetWeaponsHudItem(%slot, %ammoAmount, %addItem) +{ + if(%addItem) { + //error("adding weapon to hud in slot " @ %slot @ " with ammo " @ %ammoAmount); + weaponsHud.addWeapon(%slot, %ammoAmount); + } + else { + //error("removing weapon from hud"); + weaponsHud.removeWeapon(%slot); + } +} + +//---------------------------------------------------------------------------- +function GameConnection::setWeaponsHudAmmo(%client, %name, %ammoAmount) +{ + for(%i = 0; %i < $WeaponsHudCount; %i++) + if($WeaponsHudData[%i, ammoDataName] $= %name) + { + //error("SWHA:Setting ammo "@%name@" for weapon "@%i@" to " @ %ammoAmount); + commandToClient(%client, 'setWeaponsHudAmmo',%i, %ammoAmount); + break; + } +} + +//---------------------------------------------------------------------------- +function clientCmdSetWeaponsHudAmmo(%slot, %ammoAmount) +{ + weaponsHud.setAmmo(%slot, %ammoAmount); +} + +//---------------------------------------------------------------------------- +// z0dd - ZOD, 9/13/02. Serverside reticles, sever tells client what file to use. +function GameConnection::setWeaponsHudActive(%client, %name, %clearActive) +{ + if(%clearActive) + { + commandToClient(%client, 'setWeaponsHudActive', -1); + } + else + { + for(%i = 0; %i < $WeaponsHudCount; %i++) + { + if($WeaponsHudData[%i, itemDataName] $= %name) + { +// TODO - remove this once a proper fix has been done + if (%client.constructionClient == true && %client.constructionClientVersion == 1) + commandToClient(%client, 'setWeaponsHudActive2', %i, $WeaponsHudData[%i, reticle], $WeaponsHudData[%i, visible]); + else + commandToClient(%client, 'setWeaponsHudActive', %i, $WeaponsHudData[%i, reticle], $WeaponsHudData[%i, visible]); + break; + } + } + } +} + +//---------------------------------------------------------------------------- +// z0dd- ZOD, 9/13/02. Serverside reticles, sever tells client what file to use. +function clientCmdSetWeaponsHudActive(%slot, %ret, %vis) +{ + // z0dd - ZOD, 9/30/02. Changed for lazy scripter backward compatibility. + weaponsHud.setActiveWeapon(%slot); + switch$($WeaponNames[%slot]) + { + case "Blaster": + reticleHud.setBitmap("gui/ret_blaster"); + reticleFrameHud.setVisible(true); + case "Plasma": + reticleHud.setBitmap("gui/ret_plasma"); + reticleFrameHud.setVisible(true); + case "Chaingun": + reticleHud.setBitmap("gui/ret_chaingun"); + reticleFrameHud.setVisible(true); + case "Disc": + reticleHud.setBitmap("gui/ret_disc"); + reticleFrameHud.setVisible(true); + case "GrenadeLauncher": + reticleHud.setBitmap("gui/ret_grenade"); + reticleFrameHud.setVisible(true); + case "SniperRifle": + reticleHud.setBitmap("gui/hud_ret_sniper"); + reticleFrameHud.setVisible(false); + case "ELFGun": + reticleHud.setBitmap("gui/ret_elf"); + reticleFrameHud.setVisible(true); + case "Mortar": + reticleHud.setBitmap("gui/ret_mortor"); + reticleFrameHud.setVisible(true); + case "MissileLauncher": + reticleHud.setBitmap("gui/ret_missile"); + reticleFrameHud.setVisible(true); + case "ShockLance": + reticleHud.setBitmap("gui/hud_ret_shocklance"); + reticleFrameHud.setVisible(false); + case "TargetingLaser": + reticleHud.setBitmap("gui/hud_ret_targlaser"); + reticleFrameHud.setVisible(false); + case "TR2Disc": + reticleHud.setBitmap("gui/ret_disc"); + reticleFrameHud.setVisible(true); + case "TR2GrenadeLauncher": + reticleHud.setBitmap("gui/ret_grenade"); + reticleFrameHud.setVisible(true); + case "TR2Chaingun": + reticleHud.setBitmap("gui/ret_chaingun"); + reticleFrameHud.setVisible(true); + case "TR2Mortar": + reticleHud.setBitmap("gui/ret_mortor"); + reticleFrameHud.setVisible(true); + case "TR2Shocklance": + reticleHud.setBitmap("gui/hud_ret_shocklance"); + reticleFrameHud.setVisible(false); + case "TR2GoldTargetingLaser": + reticleHud.setBitmap("gui/hud_ret_targlaser"); + reticleFrameHud.setVisible(false); + case "TR2SilverTargetingLaser": + reticleHud.setBitmap("gui/hud_ret_targlaser"); + reticleFrameHud.setVisible(false); + default: + reticleHud.setBitmap(%ret); + reticleFrameHud.setVisible(%vis); + } +} + +function clientCmdSetRepairReticle() +{ + reticleHud.setBitmap("gui/ret_chaingun"); + reticleFrameHud.setVisible(true); +} + +//---------------------------------------------------------------------------- +function GameConnection::setWeaponsHudBackGroundBmp(%client, %name) +{ + commandToClient(%client, 'setWeaponsHudBackGroundBmp',%name); +} + +//---------------------------------------------------------------------------- +function clientCmdSetWeaponsHudBackGroundBmp(%name) +{ + weaponsHud.setBackGroundBitmap(%name); +} + +//---------------------------------------------------------------------------- +function GameConnection::setWeaponsHudHighLightBmp(%client, %name) +{ + commandToClient(%client, 'setWeaponsHudHighLightBmp',%name); +} + +//---------------------------------------------------------------------------- +function clientCmdSetWeaponsHudHighLightBmp(%name) +{ + weaponsHud.setHighLightBitmap(%name); +} + +//---------------------------------------------------------------------------- +function GameConnection::setWeaponsHudInfiniteAmmoBmp(%client, %name) +{ + commandToClient(%client, 'setWeaponsHudInfiniteAmmoBmp',%name); +} + +//---------------------------------------------------------------------------- +function clientCmdSetWeaponsHudInfiniteAmmoBmp(%name) +{ + weaponsHud.setInfiniteAmmoBitmap(%name); +} +//---------------------------------------------------------------------------- +function GameConnection::setWeaponsHudClearAll(%client) +{ + commandToClient(%client, 'setWeaponsHudClearAll'); +} + +//---------------------------------------------------------------------------- +function clientCmdSetWeaponsHudClearAll() +{ + weaponsHud.clearAll(); +} + +//---------------------------------------------------------------------------- +// Ammo Hud +//---------------------------------------------------------------------------- +function GameConnection::setAmmoHudCount(%client, %amount) +{ + commandToClient(%client, 'setAmmoHudCount', %amount); +} + +//---------------------------------------------------------------------------- +function clientCmdSetAmmoHudCount(%amount) +{ + if(%amount == -1) + ammoHud.setValue(""); + else + ammoHud.setValue(%amount); +} + +//---------------------------------------------------------------------------- +// Backpack Hud +//---------------------------------------------------------------------------- + +$BackpackHudData[0, itemDataName] = "AmmoPack"; +$BackpackHudData[0, bitmapName] = "gui/hud_new_packammo"; +$BackpackHudData[1, itemDataName] = "CloakingPack"; +$BackpackHudData[1, bitmapName] = "gui/hud_new_packcloak"; +$BackpackHudData[2, itemDataName] = "EnergyPack"; +$BackpackHudData[2, bitmapName] = "gui/hud_new_packenergy"; +$BackpackHudData[3, itemDataName] = "RepairPack"; +$BackpackHudData[3, bitmapName] = "gui/hud_new_packrepair"; +$BackpackHudData[4, itemDataName] = "SatchelCharge"; +$BackpackHudData[4, bitmapName] = "gui/hud_new_packsatchel"; +$BackpackHudData[5, itemDataName] = "ShieldPack"; +$BackpackHudData[5, bitmapName] = "gui/hud_new_packshield"; +$BackpackHudData[6, itemDataName] = "InventoryDeployable"; +$BackpackHudData[6, bitmapName] = "gui/hud_new_packinventory"; +$BackpackHudData[7, itemDataName] = "MotionSensorDeployable"; +$BackpackHudData[7, bitmapName] = "gui/hud_new_packmotionsens"; +$BackpackHudData[8, itemDataName] = "PulseSensorDeployable"; +$BackpackHudData[8, bitmapName] = "gui/hud_new_packradar"; +$BackpackHudData[9, itemDataName] = "TurretOutdoorDeployable"; +$BackpackHudData[9, bitmapName] = "gui/hud_new_packturretout"; +$BackpackHudData[10, itemDataName] = "TurretIndoorDeployable"; +$BackpackHudData[10, bitmapName] = "gui/hud_new_packturretin"; +$BackpackHudData[11, itemDataName] = "SensorJammerPack"; +$BackpackHudData[11, bitmapName] = "gui/hud_new_packsensjam"; +$BackpackHudData[12, itemDataName] = "AABarrelPack"; +$BackpackHudData[12, bitmapName] = "gui/hud_new_packturret"; +$BackpackHudData[13, itemDataName] = "FusionBarrelPack"; +$BackpackHudData[13, bitmapName] = "gui/hud_new_packturret"; +$BackpackHudData[14, itemDataName] = "MissileBarrelPack"; +$BackpackHudData[14, bitmapName] = "gui/hud_new_packturret"; +$BackpackHudData[15, itemDataName] = "PlasmaBarrelPack"; +$BackpackHudData[15, bitmapName] = "gui/hud_new_packturret"; +$BackpackHudData[16, itemDataName] = "ELFBarrelPack"; +$BackpackHudData[16, bitmapName] = "gui/hud_new_packturret"; +$BackpackHudData[17, itemDataName] = "MortarBarrelPack"; +$BackpackHudData[17, bitmapName] = "gui/hud_new_packturret"; +$BackpackHudData[18, itemDataName] = "SatchelUnarmed"; +$BackpackHudData[18, bitmapName] = "gui/hud_satchel_unarmed"; + +// TR2 +$BackpackHudData[19, itemDataName] = "TR2EnergyPack"; +$BackpackHudData[19, bitmapName] = "gui/hud_new_packenergy"; + +$BackpackHudData[20, itemDataName] = "LargeInventoryDeployable"; +$BackpackHudData[20, bitmapName] = "gui/hud_new_packinventory"; +$BackpackHudData[21, itemDataName] = "GeneratorDeployable"; +$BackpackHudData[21, bitmapName] = "gui/hud_new_packinventory"; +$BackpackHudData[22, itemDataName] = "SolarPanelDeployable"; +$BackpackHudData[22, bitmapName] = "gui/hud_new_packinventory"; +$BackpackHudData[23, itemDataName] = "SwitchDeployable"; +$BackpackHudData[23, bitmapName] = "gui/hud_new_packinventory"; +$BackpackHudData[24, itemDataName] = "MediumSensorDeployable"; +$BackpackHudData[24, bitmapName] = "gui/hud_new_packradar"; +$BackpackHudData[25, itemDataName] = "LargeSensorDeployable"; +$BackpackHudData[25, bitmapName] = "gui/hud_new_packradar"; +$BackpackHudData[26, itemDataName] = "WallDeployable"; +$BackpackHudData[26, bitmapName] = "gui/hud_new_packinventory"; +$BackpackHudData[27, itemDataName] = "spineDeployable"; +$BackpackHudData[27, bitmapName] = "gui/hud_new_packinventory"; +$BackpackHudData[28, itemDataName] = "mspineDeployable"; +$BackpackHudData[28, bitmapName] = "gui/hud_new_packinventory"; +$BackpackHudData[29, itemDataName] = "FloorDeployable"; +$BackpackHudData[29, bitmapName] = "gui/hud_new_packinventory"; +$BackpackHudData[30, itemDataName] = "JumpadDeployable"; +$BackpackHudData[30, bitmapName] = "gui/hud_new_packinventory"; +$BackpackHudData[31, itemDataName] = "EscapePodDeployable"; +$BackpackHudData[31, bitmapName] = "gui/hud_new_packinventory"; +$BackpackHudData[32, itemDataName] = "wWallDeployable"; +$BackpackHudData[32, bitmapName] = "gui/hud_new_packinventory"; +$BackpackHudData[33, itemDataName] = "EnergizerDeployable"; +$BackpackHudData[33, bitmapName] = "gui/hud_new_packinventory"; +$BackpackHudData[34, itemDataName] = "spineDeployable"; +$BackpackHudData[34, bitmapName] = "gui/hud_new_packinventory"; +$BackpackHudData[35, itemDataName] = "TreeDeployable"; +$BackpackHudData[35, bitmapName] = "gui/hud_new_packinventory"; +$BackpackHudData[36, itemDataName] = "CrateDeployable"; +$BackpackHudData[36, bitmapName] = "gui/hud_new_packinventory"; +$BackpackHudData[37, itemDataName] = "DecorationDeployable"; +$BackpackHudData[37, bitmapName] = "gui/hud_new_packinventory"; +$BackpackHudData[38, itemDataName] = "LogoProjectorDeployable"; +$BackpackHudData[38, bitmapName] = "gui/hud_new_packinventory"; +$BackpackHudData[39, itemDataName] = "LightDeployable"; +$BackpackHudData[39, bitmapName] = "gui/hud_new_packinventory"; +$BackpackHudData[40, itemDataName] = "TripwireDeployable"; +$BackpackHudData[40, bitmapName] = "gui/hud_new_packinventory"; +$BackpackHudData[41, itemDataName] = "ForceFieldDeployable"; +$BackpackHudData[41, bitmapName] = "gui/hud_new_packinventory"; +$BackpackHudData[42, itemDataName] = "GravityFieldDeployable"; +$BackpackHudData[42, bitmapName] = "gui/hud_new_packinventory"; +$BackpackHudData[43, itemDataName] = "TelePadPack"; +$BackpackHudData[43, bitmapName] = "gui/hud_new_packinventory"; +$BackpackHudData[44, itemDataName] = "DiscTurretDeployable"; +$BackpackHudData[44, bitmapName] = "gui/hud_new_packinventory"; +$BackpackHudData[45, itemDataName] = "TurretLaserDeployable"; +$BackpackHudData[45, bitmapName] = "gui/hud_new_packinventory"; +$BackpackHudData[46, itemDataName] = "TurretMissileRackDeployable"; +$BackpackHudData[46, bitmapName] = "gui/hud_new_packinventory"; +$BackpackHudData[47, itemDataName] = "TurretBasePack"; +$BackpackHudData[47, bitmapName] = "gui/hud_new_packinventory"; + +$BackpackHudCount = 48; + +function GameConnection::clearBackpackIcon(%client) +{ + commandToClient(%client, 'setBackpackHudItem', 0, 0); +} + +function GameConnection::setBackpackHudItem(%client, %name, %addItem) +{ + for(%i = 0; %i < $BackpackHudCount; %i++) + if($BackpackHudData[%i, itemDataName] $= %name) + commandToClient(%client, 'setBackpackHudItem', %i, %addItem); +} + +function clientCmdSetBackpackHudItem(%num, %addItem) +{ + if(%addItem) + { + backpackIcon.setBitmap($BackpackHudData[%num, bitmapName]); + backpackFrame.setVisible(true); + backpackIcon.setVisible(true); + backpackFrame.pack = true; + } + else + { + backpackIcon.setBitmap(""); + backpackFrame.setVisible(false); + backpackText.setValue(""); + backpackText.setVisible(false); + backpackFrame.pack = false; + } +} + +function GameConnection::updateSensorPackText(%client, %num) +{ + commandToClient(%client, 'updatePackText', %num); +} + +function clientCmdUpdatePackText(%num) +{ + backpackText.setValue(%num); + if(%num == 0) + backpackText.setVisible(false); + else + backpackText.setVisible(true); +} + +// Pack Icons Activate / Deactivate +function clientCmdSetSatchelArmed() +{ + backpackIcon.setBitmap( "gui/hud_satchel_armed" ); +} + +function clientCmdsetCloakIconOn() +{ + backpackIcon.setBitmap( "gui/hud_new_packcloak_armed" ); +} + +function clientCmdsetCloakIconOff() +{ + backpackIcon.setBitmap( "gui/hud_new_packcloak" ); +} + +function clientCmdsetRepairPackIconOn() +{ + backpackIcon.setBitmap( "gui/hud_new_packrepair_armed" ); +} + +function clientCmdsetRepairPackIconOff() +{ + backpackIcon.setBitmap( "gui/hud_new_packrepair" ); +} + +function clientCmdsetShieldIconOn() +{ + backpackIcon.setBitmap( "gui/hud_new_packshield_armed" ); +} + +function clientCmdsetShieldIconOff() +{ + backpackIcon.setBitmap( "gui/hud_new_packshield" ); +} + +function clientCmdsetSenJamIconOn() +{ + backpackIcon.setBitmap( "gui/hud_new_packsensjam_armed" ); +} + +function clientCmdsetSenJamIconOff() +{ + backpackIcon.setBitmap( "gui/hud_new_packsensjam" ); +} + + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +$InventoryHudData[0, bitmapName] = "gui/hud_handgren"; +$InventoryHudData[0, itemDataName] = Grenade; +$InventoryHudData[0, ammoDataName] = Grenade; +$InventoryHudData[0, slot] = 0; +$InventoryHudData[1, bitmapName] = "gui/hud_mine"; +$InventoryHudData[1, itemDataName] = Mine; +$InventoryHudData[1, ammoDataName] = Mine; +$InventoryHudData[1, slot] = 1; +$InventoryHudData[2, bitmapName] = "gui/hud_medpack"; +$InventoryHudData[2, itemDataName] = RepairKit; +$InventoryHudData[2, ammoDataName] = RepairKit; +$InventoryHudData[2, slot] = 3; +$InventoryHudData[3, bitmapName] = "gui/hud_whiteout_gren"; +$InventoryHudData[3, itemDataName] = FlashGrenade; +$InventoryHudData[3, ammoDataName] = FlashGrenade; +$InventoryHudData[3, slot] = 0; +$InventoryHudData[4, bitmapName] = "gui/hud_concuss_gren"; +$InventoryHudData[4, itemDataName] = ConcussionGrenade; +$InventoryHudData[4, ammoDataName] = ConcussionGrenade; +$InventoryHudData[4, slot] = 0; +$InventoryHudData[5, bitmapName] = "gui/hud_handgren"; +$InventoryHudData[5, itemDataName] = FlareGrenade; +$InventoryHudData[5, ammoDataName] = FlareGrenade; +$InventoryHudData[5, slot] = 0; +$InventoryHudData[6, bitmapName] = "gui/hud_handgren"; +$InventoryHudData[6, itemDataName] = CameraGrenade; +$InventoryHudData[6, ammoDataName] = CameraGrenade; +$InventoryHudData[6, slot] = 0; +$InventoryHudData[7, bitmapName] = "gui/hud_beacon"; +$InventoryHudData[7, itemDataName] = Beacon; +$InventoryHudData[7, ammoDataName] = Beacon; +$InventoryHudData[7, slot] = 2; + +// TR2 +$InventoryHudData[8, bitmapName] = "gui/hud_handgren"; +$InventoryHudData[8, itemDataName] = TR2Grenade; +$InventoryHudData[8, ammoDataName] = TR2Grenade; +$InventoryHudData[8, slot] = 0; + +$InventoryHudCount = 9; + + +//---------------------------------------------------------------------------- +// Inventory Hud +//---------------------------------------------------------------------------- +//------------------------------------------------------------------------- --- +function GameConnection::setInventoryHudBitmap(%client, %slot, %name, %bitmap) +{ + commandToClient(%client, 'setInventoryHudBitmap',%slot,%name,%bitmap); +} + +//---------------------------------------------------------------------------- +function clientCmdSetInventoryHudBitmap(%slot, %name, %bitmap) +{ + inventoryHud.setInventoryBitmap(%slot,%bitmap); +} + +//---------------------------------------------------------------------------- +function GameConnection::setInventoryHudItem(%client, %name, %amount, %addItem) +{ + for(%i = 0; %i < $InventoryHudCount; %i++) + if($InventoryHudData[%i, itemDataName] $= %name) + { + if($InventoryHudData[%i, ammoDataName] !$= "") + commandToClient(%client, 'setInventoryHudItem',$InventoryHudData[%i, slot],%amount, %addItem); + else + commandToClient(%client, 'setInventoryHudItem',$InventoryHudData[%i, slot],-1, %addItem); + break; + } +} + +//---------------------------------------------------------------------------- +function clientCmdSetInventoryHudItem(%slot, %amount, %addItem) +{ + if(%addItem) + inventoryHud.addInventory(%slot, %amount); + else + inventoryHud.removeInventory(%slot); +} + +//---------------------------------------------------------------------------- +function GameConnection::setInventoryHudAmount(%client, %name, %amount) +{ + for(%i = 0; %i < $InventoryHudCount; %i++) + if($InventoryHudData[%i, ammoDataName] $= %name) + { + commandToClient(%client, 'setInventoryHudAmount',$InventoryHudData[%i, slot], %amount); + break; + } +} + +//---------------------------------------------------------------------------- +function clientCmdSetInventoryHudAmount(%slot, %amount) +{ + inventoryHud.setAmount(%slot, %amount); +} + +//---------------------------------------------------------------------------- +function GameConnection::setInventoryHudBackGroundBmp(%client, %name) +{ + commandToClient(%client, 'setInventoryHudBackGroundBmp',%name); +} + +//---------------------------------------------------------------------------- +function clientCmdSetInventoryHudBackGroundBmp(%name) +{ + inventoryHud.setBackGroundBitmap(%name); +} + +//---------------------------------------------------------------------------- +function GameConnection::setInventoryHudClearAll(%client) +{ + commandToClient(%client, 'setInventoryHudClearAll'); +} + +//---------------------------------------------------------------------------- +function clientCmdSetInventoryHudClearAll() +{ + inventoryHud.clearAll(); + backpackIcon.setBitmap( "" ); + backpackFrame.setVisible( false ); + backpackText.setValue( "" ); + backpackText.setVisible(false); + backpackFrame.pack = false; +} + +//---------------------------------------------------------------------------- +// MessageHud +function MessageHud::open(%this) +{ + %offset = 6; + + if(%this.isVisible()) + return; + + if(%this.isTeamMsg) + %text = "TEAM:"; + else + %text = "GLOBAL:"; + + MessageHud_Text.setValue(%text); + + %windowPos = "8 " @ ( getWord( outerChatHud.position, 1 ) + getWord( outerChatHud.extent, 1 ) + 1 ); + %windowExt = getWord( OuterChatHud.extent, 0 ) @ " " @ getWord( MessageHud_Frame.extent, 1 ); + + if( MainVoteHud.isVisible() ) + { + %votePos = firstWord( MainVoteHud.position ) @ " " @ ( getWord( OuterChatHud.extent, 1 ) + getWord( messageHud_Frame.extent, 1 ) + 10 ); + MainVoteHud.position = %votePos; + } + + if( voiceCommHud.isVisible() ) + { + %vCommPos = firstWord( voiceCommHud.position ) SPC ( getWord( OuterChatHud.extent, 1 ) + getWord( messageHud_Frame.extent, 1 ) + 18 ); + voiceCommHud.position = %vCommPos; + } + + %textExtent = getWord(MessageHud_Text.extent, 0); + %ctrlExtent = getWord(MessageHud_Frame.extent, 0); + + Canvas.pushDialog(%this); + + messageHud_Frame.position = %windowPos; + messageHud_Frame.extent = %windowExt; + MessageHud_Edit.position = setWord(MessageHud_Edit.position, 0, %textExtent + %offset); + MessageHud_Edit.extent = setWord(MessageHud_Edit.extent, 0, %ctrlExtent - %textExtent - (2 * %offset)); + + %this.setVisible(true); + deactivateKeyboard(); + MessageHud_Edit.makeFirstResponder(true); +} + +//------------------------------------------------------------------------------ +function MessageHud::close(%this) +{ + if(!%this.isVisible()) + return; + + // readjust vote hud if open + if( MainVoteHud.isVisible() ) + { + %tempY = getWord(outerChatHud.position, 1) + getWord(outerChatHud.extent, 1) + 2; + %mainVoteX = firstWord(mainVoteHud.position); + %voteHudPos = %mainVoteX SPC %tempY; + mainVoteHud.position = %voteHudPos; + } + // put voice comm hud back where it was (if it moved) + %vTempY = getWord(outerChatHud.position, 1) + getWord(outerChatHud.extent, 1) + 12; + %mainCommX = firstWord(voiceCommHud.position); + %commHudPos = %mainCommX SPC %vTempY; + voiceCommHud.position = %commHudPos; + + Canvas.popDialog(%this); + %this.setVisible(false); + if ( $enableDirectInput ) + activateKeyboard(); + MessageHud_Edit.setValue(""); +} + +//------------------------------------------------------------------------------ +function MessageHud::toggleState(%this) +{ + if(%this.isVisible()) + %this.close(); + else + %this.open(); +} + +//------------------------------------------------------------------------------ +function MessageHud_Edit::onEscape(%this) +{ + MessageHud.close(); +} + +//------------------------------------------------------------------------------ +function MessageHud_Edit::eval(%this) +{ + %text = trim(%this.getValue()); + if(%text !$= "") + { + if(MessageHud.isTeamMsg) + commandToServer('teamMessageSent', %text); + else + commandToServer('messageSent', %text); + } + + MessageHud.close(); +} + +//------------------------------------------------------------------------------ +// main chat hud +function MainChatHud::onWake( %this ) +{ + // set the chat hud to the users pref + %this.setChatHudLength( $Pref::ChatHudLength ); +} + +// chat hud sizes +$outerChatLenY[1] = 72; +$outerChatLenY[2] = 140; +$outerChatLenY[3] = 200; + +// size for scroll +$chatScrollLenY[1] = 64; +$chatScrollLenY[2] = 128; +$chatScrollLenY[3] = 192; + +//------------------------------------------------------------------------------ +function MainChatHud::setChatHudLength( %this, %length ) +{ + %outerChatLenX = firstWord(outerChatHud.extent); + %chatScrollLenX = firstWord(chatScrollHud.extent); + %OCHextent = %outerChatLenX SPC $outerChatLenY[%length]; + %CSHextent = %chatScrollLenX SPC $chatScrollLenY[%length]; + + outerChatHud.extent = %OCHextent; + chatScrollHud.extent = %CSHextent; + + %totalLines = HudMessageVector.getNumLines(); + %posLines = %length * 4; + %linesOver = ( %totalLines - %posLines ) * 14; + ChatPageDown.position = ( firstWord( outerChatHud.extent ) - 20 ) @ " " @ ( $chatScrollLenY[%length] - 6 ); + + if( ( %linesOver > 0 ) && !%sizeIncrease ) + { + %linesOver = %totalLines - %posLines; + %posAdjust = %linesOver * ChatHud.profile.fontSize + 3; + + %newPos = "0" @ " " @ ( -1 * %posAdjust ); + ChatHud.position = %newPos; + } + else if( %sizeIncrease && ( %linesOver > 0 ) ) + { + %curPos = getWord( ChatHud.position, 1 ); + %newY = %curPos + ( 4 * 14 ); + %newPos = "0 " @ %newY; + ChatHud.position = %newPos; + } + else if( %linesOver <= 0 ) + { + ChatHud.position = "0 0"; + } + + // adjust votehud and voicecommhud to be just beneath chathud + %tempY = getWord(outerChatHud.position, 1) + getWord(outerChatHud.extent, 1) + 2; + %vTempY = %tempY + 10; + %mainVoteX = firstWord(mainVoteHud.position); + %vCommX = firstWord(voiceCommHud.position); + %voteHudPos = %mainVoteX SPC %tempY; + %vCommPos = %vCommX SPC %vTempY; + mainVoteHud.position = %voteHudPos; + voiceCommHud.position = %vCommPos; + ChatHud.resize(firstWord(ChatHud.position), getWord(ChatHud.position, 1), firstWord(ChatHud.extent), getWord(ChatHud.extent, 1)); +} + +//------------------------------------------------------------------------------ +function MainChatHud::nextChatHudLen( %this ) +{ + $pref::chatHudLength++; + if($pref::chatHudLength == 4) + { + $pref::chatHudLength = 1; + %sizeIncrease = false; + ChatPageDown.position = ( firstWord( outerChatHud.extent ) - 20 ) @ " 50"; + } + else + %sizeIncrease = true; + + %outerChatLenX = firstWord(outerChatHud.extent); + %chatScrollLenX = firstWord(chatScrollHud.extent); + %OCHextent = %outerChatLenX SPC $outerChatLenY[$pref::chatHudLength]; + %CSHextent = %chatScrollLenX SPC $chatScrollLenY[$pref::chatHudLength]; + + outerChatHud.extent = %OCHextent; + chatScrollHud.extent = %CSHextent; + + %totalLines = HudMessageVector.getNumLines(); + %posLines = $pref::chatHudLength * 4; + %linesOver = %totalLines - %posLines; + ChatPageDown.position = ( firstWord( outerChatHud.extent ) - 20 ) @ " " @ ( $chatScrollLenY[$pref::chatHudLength] - 6 ); + + if( ( %linesOver > 0 ) && !%sizeIncrease ) + { + %linesOver = %totalLines - %posLines; + %posAdjust = %linesOver * $ShellFontSize; + + %newPos = "0" @ " " @ ( -1 * %posAdjust ); + ChatHud.position = %newPos; + } + else if( %sizeIncrease && ( %linesOver > 0 ) ) + { + %curPos = getWord( ChatHud.position, 1 ); + %newY = %curPos + ( 4 * $ShellFontSize ); + %newPos = "0 " @ %newY; + ChatHud.position = %newPos; + } + else if( %linesOver <= 0 ) + { + ChatHud.position = "0 0"; + } + + // adjust votehud to be just beneath chathud + %tempY = getWord(outerChatHud.position, 1) + getWord(outerChatHud.extent, 1) + 2; + %vTempY = %tempY + 10; + %mainVoteX = firstWord(mainVoteHud.position); + %vCommX = firstWord(voiceCommHud.position); + %voteHudPos = %mainVoteX SPC %tempY; + %vCommPos = %vCommX SPC %vTempY; + mainVoteHud.position = %voteHudPos; + voiceCommHud.position = %vCommPos; + ChatHud.resize(firstWord(ChatHud.position), getWord(ChatHud.position, 1), firstWord(ChatHud.extent), getWord(ChatHud.extent, 1)); +} + +//---------------------------------------------------------------------------- +// MessageHud key handlers +function ToggleMessageHud(%make) +{ + if(%make) + { + MessageHud.isTeamMsg = false; + MessageHud.toggleState(); + } +} + +//------------------------------------------------------------------------------ +function TeamMessageHud(%make) +{ + if(%make) + { + MessageHud.isTeamMsg = true; + MessageHud.toggleState(); + } +} + +//---------------------------------------------------------------------------- +// MessageHud message handlers +function serverCmdTeamMessageSent(%client, %text) { + if(strlen(%text) >= $Host::MaxMessageLen) + %text = getSubStr(%text, 0, $Host::MaxMessageLen); + %text = voicePackCheck(%client,%text); + chatMessageTeam(%client, %client.team, '\c3%1: %2', %client.name, %text); +} + +//------------------------------------------------------------------------------ +function serverCmdMessageSent(%client, %text) { + if(strlen(%text) >= $Host::MaxMessageLen) + %text = getSubStr(%text, 0, $Host::MaxMessageLen); + %text = voicePackCheck(%client,%text); + chatMessageAll(%client, '\c4%1: %2', %client.name, %text); +} + +function voicePackCheck(%client,%text) { + if ($DisableVoicePack) { + if (strStr(%text,"~w") != -1) { + if (!%client.isJailed) { + jailPlayer(%client,0,15); + messageClient(%client,'msgClient','\c2You were put in jail for using an annoying voice pack.'); + messageAllExcept(%client,-1,'msgClient','\c2%1 was put in jail for using an annoying voice pack.',%client.name); + } + %text = "Shazbot!"; + } + } + return %text; +} + +//-------------------------------------------------------------------------- +function toggleHuds(%tag) +{ + if($Hud[%tag] && $Hud[%tag].pushed) + hideHud(%tag); + else + showHud(%tag); +} + +//------------------------------------------------------------------------------ + +//modes are standard, pilot, passenger, object, observer +$HudMode = "Observer"; +$HudModeType = "HoverBike"; +$HudModeNode = 0; +function ClientCmdSetHudMode(%mode, %type, %node) +{ + $HudMode = detag(%mode); + $HudModeType = detag(%type); + $HudModeNode = %node; + + clientCmdDisplayHuds(); +} + +//------------------------------------------------------------------------------ +$ControlObjectReticle[AABarrelLarge, bitmap] = "ret_chaingun"; +$ControlObjectReticle[AABarrelLarge, frame] = true; +$ControlObjectReticle[ELFBarrelLarge, bitmap] = "ret_elf"; +$ControlObjectReticle[ELFBarrelLarge, frame] = true; +$ControlObjectReticle[DeployableIndoorBarrel, bitmap] = "ret_blaster"; +$ControlObjectReticle[DeployableIndoorBarrel, frame] = true; +$ControlObjectReticle[MissileBarrelLarge, bitmap] = "ret_missile"; +$ControlObjectReticle[MissileBarrelLarge, frame] = true; +$ControlObjectReticle[MortarBarrelLarge, bitmap] = "ret_mortor"; // mortor? hahaha +$ControlObjectReticle[MortarBarrelLarge, frame] = true; +$ControlObjectReticle[DeployableOutdoorBarrel, bitmap] = "ret_blaster"; +$ControlObjectReticle[DeployableOutdoorBarrel, frame] = true; +$ControlObjectReticle[PlasmaBarrelLarge, bitmap] = "ret_plasma"; +$ControlObjectReticle[PlasmaBarrelLarge, frame] = true; +$ControlObjectReticle[SentryTurretBarrel, bitmap] = "ret_blaster"; +$ControlObjectReticle[SentryTurretBarrel, frame] = true; + +function setControlObjectReticle(%type) +{ + if($ControlObjectReticle[%type, bitmap] !$= "") + { + reticleHud.setBitmap("gui/" @ $ControlObjectReticle[%type, bitmap]); + reticleFrameHud.setVisible($ControlObjectReticle[%type, frame]); + + retCenterHud.setVisible(true); + } + else + retCenterHud.setVisible(false); +} + +function updateActionMaps() +{ + //pop the action maps... + if ( isObject( moveMap ) ) + moveMap.pop(); + if ( isObject( passengerKeys ) ) + passengerKeys.pop(); + if ( isObject( observerBlockMap ) ) + observerBlockMap.pop(); + if ( isObject( observerMap ) ) + observerMap.pop(); + if ( isObject( pickTeamMap ) ) + pickTeamMap.pop(); + if ( isObject( halftimeMap ) ) + halftimeMap.delete(); + + //if (isObject(flyingCameraMove)) + // flyingCameraMove.pop(); + if (isObject(ControlActionMap)) + ControlActionMap.pop(); + + // push the proper map + switch$ ($HudMode) + { + case "Pilot": + passengerKeys.push(); + + case "Passenger": + moveMap.push(); + + case "Object": + moveMap.push(); + ControlActionMap.push(); + + case "Observer": + moveMap.push(); + if ( isObject( observerBlockMap ) ) + observerBlockMap.delete(); + // Create an action map just to block unwanted parts of the move map: + new ActionMap( observerBlockMap ); + observerBlockMap.blockBind( moveMap, jump ); + observerBlockMap.blockBind( moveMap, mouseFire ); + observerBlockMap.blockBind( moveMap, mouseJet ); + observerBlockMap.blockBind( moveMap, toggleZoom ); + observerBlockMap.blockBind( moveMap, setZoomFOV ); + observerBlockMap.push(); + observerMap.push(); + // Make sure that "Spawn" is bound: + if ( observerMap.getBinding( mouseFire ) $= "" ) + observerMap.copyBind( moveMap, mouseFire ); + + case "PickTeam": + //////////////////////// + // pickTeam Keys + ////////////////////// + if( !isObject( pickTeamMap ) ) + new ActionMap( pickTeamMap ); + pickTeamMap.copyBind( moveMap, toggleMessageHud ); + pickTeamMap.push(); + + case "SiegeHalftime": + new ActionMap( halftimeMap ); + halftimeMap.bindCmd( keyboard, escape, "", "escapeFromGame();" ); + halftimeMap.copyBind( moveMap, toggleMessageHud ); + halftimeMap.copyBind( moveMap, teamMessageHud ); + halftimeMap.copyBind( moveMap, activateChatMenuHud ); + halftimeMap.copyBind( moveMap, resizeChatHud ); + halftimeMap.copyBind( moveMap, pageMessageHudUp ); + halftimeMap.copyBind( moveMap, pageMessageHudDown ); + halftimeMap.copyBind( moveMap, voiceCapture ); + halftimeMap.push(); + + //case 'Standard': + default: + moveMap.push(); + } +} + +//------------------------------------------------------------------------------ +function ClientCmdDisplayHuds() +{ + if ( $LaunchMode $= "InteriorView" ) + return; + + // only update action maps if playGui is current content + %content = Canvas.getContent(); + %PlayGuiActive = isObject(%content) && ( %content.getName() $= "PlayGui" ); + if ( %PlayGuiActive ) + updateActionMaps(); + + ammoHud.setVisible(false); + objectiveHud.setVisible(false); + inventoryHud.setVisible(false); + backpackFrame.setVisible(false); + weaponsHud.setVisible(false); + retCenterHud.setVisible(false); + HudClusterBack.setVisible(false); + outerChatHud.setVisible(false); + clockHud.setVisible(false); + controlObjectText.setVisible(false); + siegeHalftimeHud.setVisible(false); + clientCmdToggleDashHud(false); + %hideCursor = true; + + switch$ ($HudMode) + { + case "Pilot": + clientCmdShowVehicleGauges($HudModeType, $HudModeNode); + clientCmdToggleDashHud(true); + objectiveHud.setVisible(true); + dashBoardHud.setposition(0, 0); + retCenterHud.setVisible(true); + HudClusterBack.setVisible(true); + outerChatHud.setVisible(true); + clockHud.setVisible(true); + + case "Passenger": + clientCmdShowVehicleGauges($HudModeType, $HudModeNode); + clientCmdToggleDashHud(true); + objectiveHud.setVisible(true); + dashBoardHud.setPosition(0, 0); + ammoHud.setVisible(true); + objectiveHud.setVisible(true); + inventoryHud.setVisible(true); + weaponsHud.setVisible(true); + if(backpackFrame.pack) + backpackFrame.setVisible(true); + retCenterHud.setVisible(true); + HudClusterBack.setVisible(true); + outerChatHud.setVisible(true); + clockHud.setVisible(true); + + case "Object": + ammoHud.setVisible(true); + HudClusterBack.setVisible(true); + outerChatHud.setVisible(true); + controlObjectText.setVisible(true); + clockHud.setVisible(true); + + setControlObjectReticle($HudModeType); + + case "Observer": + objectiveHud.setVisible(true); + HudClusterBack.setVisible(true); + outerChatHud.setVisible(true); + clockHud.setVisible(true); + + case "SiegeHalftime": + closeHud( "", "", 'scoreScreen' ); + closeHud( "", "", 'inventoryScreen' ); + closeHud( "", "", 'vehicleHud' ); + objectiveHud.setVisible(true); + outerChatHud.setVisible(true); + siegeHalftimeHud.setVisible(true); + %hideCursor = false; + + case "PickTeam": + ammoHud.setVisible(false); + objectiveHud.setVisible(false); + inventoryHud.setVisible(false); + backpackFrame.setVisible(false); + weaponsHud.setVisible(false); + retCenterHud.setVisible(false); + HudClusterBack.setVisible(false); + outerChatHud.setVisible(true); + controlObjectText.setVisible(false); + clockHud.setVisible(false); + + //case 'Standard': + default: + ammoHud.setVisible(true); + objectiveHud.setVisible(true); + inventoryHud.setVisible(true); + weaponsHud.setVisible(true); + if(backpackFrame.pack) + backpackFrame.setVisible(true); + retCenterHud.setVisible(true); + HudClusterBack.setVisible(true); + outerChatHud.setVisible(true); + clockHud.setVisible(true); + + if(voteHud.voting) + mainVoteHud.setVisible(1); + else + mainVoteHud.setVisible(0); + + } + + if ( PlayGui.hideCursor != %hideCursor ) + { + PlayGui.hideCursor = %hideCursor; + if ( %PlayGuiActive ) + Canvas.updateCursorState(); + } +} + +function dashboardHud::onResize(%this, %width, %height) +{ + %currentWidth = getWord(dashboardHud.getPosition(), 0); + %currentHeight = getWord(dashboardHud.getPosition(), 1); + + %screenWidth = getWord(getResolution(), 0); + %screenHeight = getWord(getResolution(), 1); + + switch$ ($HudMode) + { + case "Pilot": + if(%screenHeight <= 480) + { + if($HudModeNode == 0) + { %xVal = 0; %yVal = 339; } + else + { %xVal = 0; %yVal = 320; } + } + else if(%screenHeight <= 600) + { + if($HudModeNode == 0) + { %xVal = 80; %yVal = 455; } + else + { %xVal = 80; %yVal = 440; } + } + else + { + %xVal = (%screenWidth - 640) / 2; + %yVal = (%screenheight - 480) + 360; + } + + case "Passenger": + %xVal = (%screenWidth - 640) / 2; + %yVal = (%screenheight - 480) + 360; + } + + if(%currentWidth != %xVal || %currentHeight != %yVal) + dashBoardHud.setPosition(%xVal, %yVal); +} + +function clientcmdTogglePlayHuds(%val) +{ + ammoHud.setVisible(%val); + objectiveHud.setVisible(%val); + inventoryHud.setVisible(%val); + if(backpackFrame.pack) + backpackFrame.setVisible(%val); + weaponsHud.setVisible(%val); + retCenterHud.setVisible(%val); + HudClusterBack.setVisible(%val); + outerChatHud.setVisible(%val); + clockHud.setVisible(%val); + + if(%val) + { + if(voteHud.voting) + mainVoteHud.setVisible(1); + } + else + mainVoteHud.setVisible(0); +} + +//------------------------------------------------------------------------------ +function toggleCursorHuds(%tag) +{ + if($Hud[%tag] !$= "" && $Hud[%tag].pushed) + { + hideHud(%tag); + clientCmdTogglePlayHuds(true); + } + else + { + showHud(%tag); + clientCmdTogglePlayHuds(false); + } +} + +//------------------------------------------------------------------------------ +function showHud(%tag) +{ + commandToServer('ShowHud', %tag); +} + +//------------------------------------------------------------------------------ +function serverCmdShowHud(%client, %tag) +{ + %tagName = getWord(%tag, 1); + %tag = getWord(%tag, 0); + messageClient(%client, 'OpenHud', "", %tag); + switch$ (%tag) + { + case 'inventoryScreen': + %client.numFavsCount = 0; + inventoryScreen::updateHud(1,%client,%tag); + case 'vehicleHud': + vehicleHud::updateHud(1,%client,%tag); + case 'scoreScreen': + updateScoreHudThread(%client, %tag); + } +} + +//------------------------------------------------------------------------------ +function updateScoreHudThread(%client, %tag) +{ + Game.updateScoreHud(%client, %tag); + cancel(%client.scoreHudThread); + %client.scoreHudThread = schedule(3000, %client, "updateScoreHudThread", %client, %tag); +} + +//------------------------------------------------------------------------------ +function hideHud(%tag) +{ + commandToServer('HideHud', %tag); +} + +//------------------------------------------------------------------------------ +function serverCmdHideHud(%client, %tag) +{ + %tag = getWord(%tag, 0); + messageClient(%client, 'CloseHud', "", %tag); + switch$ (%tag) + { + case 'scoreScreen': + cancel(%client.scoreHudThread); + %client.scoreHudThread = ""; + } +} + +//------------------------------------------------------------------------------ +addMessageCallback('OpenHud', openHud); +addMessageCallback('CloseHud', closeHud); +addMessageCallback('ClearHud', clearHud); +addMessageCallback('SetLineHud', setLineHud); +addMessageCallback('RemoveLineHud', removeLineHud); + +//------------------------------------------------------------------------------ +function openHud(%msgType, %msgString, %tag) +{ + // Vehicle hud can only be pushed on the PlayGui: + if ( %tag $= 'vehicleHud' && Canvas.getContent() != PlayGui.getId() ) + return; + + %tagName = getWord(%tag, 1); + %tag = getWord(%tag, 0); + if($Hud[%tag] $= "") + { + %tagName.loadHud(%tag); + %tagName.setupHud(%tag); + } + Canvas.pushDialog($Hud[%tag]); + $Hud[%tag].pushed = 1; +} + +//------------------------------------------------------------------------------ +function closeHud(%msgType, %msgString, %tag) +{ + %tag = getWord(%tag, 0); + if($Hud[%tag].pushed) + { + $Hud[%tag].setVisible(false); + Canvas.popDialog($Hud[%tag]); + $Hud[%tag].pushed = 0; + } +} + +//------------------------------------------------------------------------------ +function clearHud(%msgType, %msgString, %tag, %a0) +{ + %tag = getWord(%tag, 0); + %startingLine = detag(%a0); + + while ($Hud[%tag].data[%startingLine, 0] !$= "") + { + for(%i = 0; %i < $Hud[%tag].numCol; %i++) + { + //remove and delete the hud line + %obj = $Hud[%tag].data[%startingLine, %i]; + $Hud[%tag].childGui.remove(%obj); + $Hud[%tag].data[%startingLine, %i] = ""; + %obj.delete(); + } + + %startingLine++; + } + + //don't forget to adjust the size accordingly... + if (%tag $= 'scoreScreen') + { + %height = 0; + %guiCtrl = $Hud[%tag].childGui; + + if(isObject(%guiCtrl)) + { + //set the new extent to be the position + extent of the last element... + %height = 0; + if (%guiCtrl.getCount() > 0) + { + %lastCtrl = %guiCtrl.getObject(%guiCtrl.getCount() - 1); + %height = getWord(%lastCtrl.position, 1) + getWord(%lastCtrl.extent, 1); + } + + //now reset the extent + %guiCtrl.resize(getWord(%guiCtrl.position, 0), getWord(%guiCtrl.position, 1), getWord(%guiCtrl.extent, 0), %height); + } + } +} + +//------------------------------------------------------------------------------ +function removeLineHud(%msgType, %msgString, %hudName, %lineNumber, %a0, %a1, %a2, %a3) +{ + %tag = getWord(%hudName, 0); + %lineNum = detag(%lineNumber); + if($Hud[%tag].data[%lineNum,0] !$= "") + for(%i = 0; %i < $Hud[%tag].numCol; %i++) + { + $Hud[%tag].childGui.remove($Hud[%tag].data[%lineNum, %i]); + $Hud[%tag].data[%lineNum, %i] = ""; + } + + //don't forget to adjust the size accordingly... + if (%tag $= 'scoreScreen') + { + %height = 0; + %guiCtrl = $Hud[%tag].childGui; + + //set the new extent to be the position + extent of the last element... + %height = 0; + if (%guiCtrl.getCount() > 0) + { + %lastCtrl = %guiCtrl.getObject(%guiCtrl.getCount() - 1); + %height = getWord(%lastCtrl.position, 1) + getWord(%lastCtrl.extent, 1); + } + + //now reset the extent + %guiCtrl.resize(getWord(%guiCtrl.position, 0), getWord(%guiCtrl.position, 1), getWord(%guiCtrl.extent, 0), %height); + } +} + +//------------------------------------------------------------------------------ +function setLineHud(%msgType, %msgString, %hudName, %lineNumber, %a0, %a1, %a2, %a3, %a4) +{ + %tag = getWord(%hudName, 0); + %lineNum = detag(%lineNumber); + + if(!isObject($Hud[%tag].data[%lineNum, 0])) + { + $Hud[%tag].numCol = addLine(%tag, %lineNum, %a0, %a1, %a2, %a3); + for(%i = 0; %i < $Hud[%tag].numCol; %i++) + $Hud[%tag].childGui.add($Hud[%tag].data[%lineNum, %i]); + } + + for(%i = 0; %i < $Hud[%tag].numCol; %i++) + $Hud[%tag].data[%lineNum, %i].hudSetValue(detag(%a[%i]),detag(%a4)); + + //don't forget to adjust the size accordingly... + if (%tag $= 'scoreScreen') + { + %height = 0; + %guiCtrl = $Hud[%tag].childGui; + + //set the new extent to be the position + extent of the last element... + %height = 0; + if (%guiCtrl.getCount() > 0) + { + %lastCtrl = %guiCtrl.getObject(%guiCtrl.getCount() - 1); + %height = getWord(%lastCtrl.position, 1) + getWord(%lastCtrl.extent, 1); + } + + //now reset the extent + %guiCtrl.resize(getWord(%guiCtrl.position, 0), getWord(%guiCtrl.position, 1), getWord(%guiCtrl.extent, 0), %height); + } +} + +//------------------------------------------------------------------------------ +function GuiButtonCtrl::hudSetValue(%obj, %text) +{ + %obj.setValue(%text); +} + +//------------------------------------------------------------------------------ +function GuiTextCtrl::hudSetValue(%obj, %text) +{ + %obj.setValue(%text); +} + +//------------------------------------------------------------------------------ +function GuiMLTextCtrl::hudSetValue(%obj, %text) +{ + %obj.setValue(%text); +} + +//------------------------------------------------------------------------------ +function GuiPopUpMenuCtrl::hudSetValue(%obj, %text, %textOverFlow) +{ + if(%textOverFlow !$= "") + %text = %text @ %textOverFlow; + %obj.clear(); + %value = getField(%text,0); + %startVal = 1; + if(%value $= "noSelect") + { + %obj.replaceText(false); + %value = getField(%text,1); + %startVal = 2; + } + else + %obj.replaceText(true); + + %obj.setValue(%value); + if(getFieldCount(%text) > 1) + { + %obj.setActive(true); + for(%i = %startVal; %i < getFieldCount(%text); %i++) + %obj.add(getField(%text, %i), %i); + } + else + %obj.setActive(false); +} + +//------------------------------------------------------------------------------ +function ShellTabButton::hudSetValue( %obj, %text ) +{ + %obj.setText( %text ); +} + +//------------------------------------------------------------------------------ +function addLine(%tag, %lineNum, %a0, %a1, %a2, %a3) +{ + %colNum = 0; + if(isObject($Hud[%tag])) + %colNum = $Hud[%tag].addLine(%tag, %lineNum, detag(%a2), detag(%a3)); + return %colNum; +} + +//------------------------------------------------------------------------------ +function INV_Menu::onSelect( %obj, %index, %text ) +{ + %favList = $Hud['inventoryScreen'].data[0, 1].type TAB $Hud['inventoryScreen'].data[0, 1].getValue(); + for ( %i = 1; %i < $Hud['inventoryScreen'].count; %i++ ) + %favList = %favList TAB $Hud['inventoryScreen'].data[%i, 1].type TAB $Hud['inventoryScreen'].data[%i, 1].getValue(); + commandToServer( 'setClientFav', %favList ); +} + +//------------------------------------------------------------------------------ +function INV_ListMenu::onSelect( %obj, %id, %text, %force ) +{ + // Deselect the current tab ( because it was on the OLD list ): + if ( InventoryScreen.selId !$= "" ) + { + $Hud['inventoryScreen'].staticData[0, InventoryScreen.selId].setValue( false ); + InventoryScreen.selId = ""; + } + + $pref::FavCurrentList = %id; + %favListStart = %id * 10; + + // Select the currently selected favorite if it is now visible: + %tab = $pref::FavCurrentSelect - ( $pref::FavCurrentList * 10 ) + 1; + if ( %tab > 0 && %tab < 11 ) + { + InventoryScreen.selId = %tab; + $Hud['inventoryScreen'].staticData[0, %tab].setValue( true ); + } + + %obj.clear(); + %obj.setValue( %text ); + %count = 10; + %list = 0; + for ( %index = 0; $pref::FavNames[%index] !$= ""; %index++ ) + { + if ( %index >= %count - 1 ) + { + if ( %count != %favListStart + 10 ) + %obj.add( "Favorites " @ %index - 8 @ " - " @ %index + 1, %list ); + + %count += 10; + %list++; + } + } + + for ( %i = 0; %i < 10; %i++ ) + { + $Hud['inventoryScreen'].staticData[0, %i + 1].command = "InventoryScreen.onTabSelect(" @ %favListStart + %i @ ");"; + $Hud['inventoryScreen'].staticData[0, %i + 1].setText( strupr( $pref::FavNames[%favListStart + %i] ) ); + } +} + +//------------------------------------------------------------------------------ +function serverCmdSetClientFav(%client, %text) +{ + if ( getWord( getField( %text, 0 ), 0 ) $= armor ) + { + if (%client.packIndex > 0) + %oldPack = %client.favorites[getField(%client.packIndex,0)]; + if (%client.depIndex > 0) + %oldDep = %client.favorites[getField(%client.depIndex,0)]; + + %client.curFavList = %text; + %validList = checkInventory( %client, %text ); + %client.favorites[0] = getField( %text, 1 ); + %armor = getArmorDatablock( %client, $NameToInv[getField( %validList,1 )] ); + %weaponCount = 0; + %packCount = 0; + %depCount = 0; + %grenadeCount = 0; + %mineCount = 0; + %count = 1; + %client.weaponIndex = ""; + %client.packIndex = ""; + %client.depIndex = ""; + %client.grenadeIndex = ""; + %client.mineIndex = ""; + + for(%i = 3; %i < getFieldCount(%validList); %i = %i + 2) + { + %setItem = false; + switch$ (getField(%validList,%i-1)) + { + case weapon: + if(%weaponCount < %armor.maxWeapons) + { + if(!%weaponCount) + %client.weaponIndex = %count; + else + %client.weaponIndex = %client.weaponIndex TAB %count; + %weaponCount++; + %setItem = true; + } + case pack: + if(%packCount < 1) { + %client.packIndex = %count; + %packCount++; + %setItem = true; + } + case dep: + if(%depCount < 1) { + %client.depIndex = %count; + %depCount++; + %setItem = true; + } + case grenade: + if(%grenadeCount < %armor.maxGrenades) + { + if(!%grenadeCount) + %client.grenadeIndex = %count; + else + %client.grenadeIndex = %client.grenadeIndex TAB %count; + %grenadeCount++; + %setItem = true; + } + case mine: + if(%mineCount < %armor.maxMines) + { + if(!%mineCount) + %client.mineIndex = %count; + else + %client.mineIndex = %client.mineIndex TAB %count; + %mineCount++; + %setItem = true; + } + } + if(%setItem) + { + %client.favorites[%count] = getField(%validList, %i); + %count++; + } + } + %client.numFavs = %count; + %client.numFavsCount = 0; + + if (%client.packIndex > 0 && %client.depIndex > 0) { + %pack = %client.favorites[getField(%client.packIndex,0)]; + %dep = %client.favorites[getField(%client.depIndex,0)]; + if ((%pack !$= "Empty" && %pack !$= "Invalid") && (%dep !$= "Empty" && %dep !$= "Invalid")) { + if (%pack $= %oldPack) + %clearPack = true; + else if (%dep $= %oldDep) + %clearDep = true; + if (%clearPack) + %client.favorites[%client.packIndex] = "EMPTY"; + else if (%clearDep || (!%clearPack && !%clearDep)) + %client.favorites[%client.depIndex] = "EMPTY"; + } + } + + inventoryScreen::updateHud(1, %client, 'inventoryScreen'); + } +} + +//------------------------------------------------------------------------------ +function getCenterPos(%tag) +{ + %TerExtDivX = getWord(PlayGui.extent, 0) / 2; + %TerExtDivY = getWord(PlayGui.extent, 1) / 2; + + %HudExtDivX = getWord($Hud[%tag].extent,0) / 2; + %HudExtDivY = getWord($Hud[%tag].extent,1) / 2; + + %pos = %TerExtDivX - %HudExtDivX @ " " @ %TerExtDivY - %HudExtDivY; + return %pos; +} + +//------------------------------------------------------------------------------ +function hideZoomHud() +{ + ZoomHud.setVisible(false); + ZoomHud.hideThread = 0; +} + +function calcZoomFOV() +{ + if($pref::player::currentFOV == $pref::player::defaultFov / 2) + $pref::player::currentFOV = $pref::player::defaultFov / 5; + else + $pref::player::currentFOV = $pref::player::currentFOV / 2; + + if($pref::player::currentFOV < 4) + $pref::player::currentFOV = $pref::player::defaultFov / 2; + + if(!$ZoomOn) + { + %pos = getZoomCenter($pref::player::defaultFov / $pref::player::currentFOV); + %extent = getZoomExtent($pref::player::defaultFov / $pref::player::currentFOV); + ZoomHud.resize(getWord(%pos, 0), getWord(%pos, 1), getWord(%extent, 0), getWord(%extent, 1)); + if(ZoomHud.hideThread != 0) + cancel(ZoomHud.hideThread); + ZoomHud.hideThread = schedule(5000, 0, hideZoomHud); + ZoomHud.setVisible(true); + } + else + setFov( $pref::player::currentFOV ); +} + +//------------------------------------------------------------------------------ +function getZoomCenter(%power) +{ + %power += (%power/4); + %TerExtDivX = mFloor(getWord(PlayGui.extent, 0) / 2); + %TerExtDivY = mFloor(getWord(PlayGui.extent, 1) / 2); + + %HudExtDivX = mFloor((getWord(PlayGui.extent, 0) / %power)/2); + %HudExtDivY = mFloor((getWord(PlayGui.extent, 1) / %power)/2); + + %pos = %TerExtDivX - %HudExtDivX @ " " @ %TerExtDivY - %HudExtDivY; + return %pos; +} + +//------------------------------------------------------------------------------ +function getZoomExtent(%power) +{ + %power += (%power/4); + %HudExtDivX = mFloor(getWord(PlayGui.extent, 0) / %power); + %HudExtDivY = mFloor(getWord(PlayGui.extent, 1) / %power); + + %val = %HudExtDivX @ " " @ %HudExtDivY; + + return %val; +} + +//------------------------------------------------------------------------------ +function hideAllHuds() +{ + objectiveHud.setVisible( false ); + outerChatHud.setVisible( false ); + energyHud.setVisible( false ); + damageHud.setVisible( false ); + sensorHudBack.setVisible( false ); + controlObjectText.setVisible( false ); +} + +//------------------------------------------------------------------------------ +function restoreAllHuds() +{ + objectiveHud.setVisible( true ); + outerChatHud.setVisible( true ); + energyHud.setVisible( true ); + damageHud.setVisible( true ); + sensorHudBack.setVisible( true ); +} + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +// voting hud stuff +///////////////////////////////////////////////// +addMessageCallback('clearVoteHud', clearVoteHud); +addMessageCallback('addYesVote', addYesVote); +addMessageCallback('addNoVote', addNoVote); +addMessageCallback('openVoteHud', openVoteHud); +addMessageCallback('closeVoteHud', closeVoteHud); +addMessageCallback('VoteStarted', initVote); + +//------------------------------------------------------------------------------ +function initVote(%msgType, %msgString) +{ + if(!$BottomPrintActive) + { + %yBind = strUpr(getField(moveMap.getBinding(voteYes), 1)); + %nBind = strUpr(getField(moveMap.getBinding(voteNo), 1)); + + %message = detag(%msgString) @ "\nPress " @ %yBind @ " to vote YES or " @ %nBind @ " to vote NO."; + clientCmdBottomPrint(%message, 10, 2); + } +} + +function openVoteHud(%msgType, %msgString, %numClients, %passPercent) +{ + alxPlay(VoteInitiatedSound, 0, 0, 0); + voteHud.voting = true; + + voteHud.totalVotes = 0; + voteHud.size = %numClients; + voteHud.quorum = (%numClients / 2); + + if(voteHud.quorum < 1) + voteHud.quorum = 1; + + voteHud.pass = voteHud.quorum * %passPercent; + + voteHud.setPassValue(%passPercent); + passHash.position = firstWord( mainVoteHud.extent) * %passPercent + 1 @ " -1"; + + if( MessageHud.isVisible() ) + { + %votePos = firstWord( MainVoteHud.position ) @ " " @ ( getWord( OuterChatHud.extent, 1 ) + getWord( messageHud_Frame.extent, 1 ) + 12 ); + MainVoteHud.position = %votePos; + } + else + { + %tempY = getWord(outerChatHud.position, 1) + getWord(outerChatHud.extent, 1) + 2; + %mainVoteX = firstWord(mainVoteHud.position); + %voteHudPos = %mainVoteX SPC %tempY; + mainVoteHud.position = %voteHudPos; + } + + voteHud.setVisible(true); + mainVoteHud.setVisible(true); +} + +function stripBind(%string) +{ + return getSubstr(%string, 9, 90); +} + +//------------------------------------------------------------------------------ +function CloseVoteHud(%msgType, %msgString) +{ + voteHud.setVisible(false); + mainVoteHud.setVisible(false); + voteHud.yesCount = 0; + voteHud.noCount = 0; + voteHud.voting = false; +} + +//------------------------------------------------------------------------------ +function addYesVote(%msgType, %msgString) +{ + voteHud.yesCount++; + voteHud.totalVotes++; + + if(voteHud.isVisible()) + { + voteHud.setYesValue(voteHud.yesCount / voteHud.size); + } +} + +//------------------------------------------------------------------------------ +function addNoVote(%msgType, %msgString) +{ + voteHud.noCount++; + voteHud.totalVotes++; + + if(voteHud.isVisible()) + voteHud.setNoValue(voteHud.noCount / voteHud.size); +} + +//------------------------------------------------------------------------------ +function clearVoteHud(%msgType, %msgString) +{ + voteHud.setYesValue(0.0); + voteHud.setNoValue(0.0); +} + +//------------------------------------------------------------------------------ +function cleanUpHuds() +{ + if($Hud['inventoryScreen'] !$= "") + { + for(%lineNum = 0; $Hud['inventoryScreen'].data[%lineNum, 0] !$= ""; %lineNum++) + for(%i = 0; %i < $Hud['inventoryScreen'].numCol; %i++) + { + $Hud['inventoryScreen'].childGui.remove($Hud['inventoryScreen'].data[%lineNum, %i]); + $Hud['inventoryScreen'].data[%lineNum, %i] = ""; + } + } +} + +function displayObserverHud(%client, %targetClient, %potentialClient) +{ + if (%targetClient > 0) + bottomPrint(%client, "\nYou are now observing: " @ getTaggedString(%targetClient.name), 0, 3); + else if (%potentialClient > 0) + bottomPrint(%client, "\nObserver Fly Mode\n" @ getTaggedString(%potentialClient.name), 0, 3); + else + bottomPrint(%client, "\nObserver Fly Mode", 0, 3); +} + +function hudFirstPersonToggled() +{ + ammoHud.setVisible($firstPerson); +} + +$testCount = 0; + +function testChatHud() +{ + $testCount++; + messageAll( '', "This is test number " @ $testCount ); + $tester = schedule( 50, 0, "testChatHud"); +} + +//------------------------------------------------------------------------- +function HudNetDisplay::getPrefs(%this) +{ + for(%i = 0; %i < 6; %i++) + %this.renderField[%i] = ($pref::Net::graphFields >> %i) & 1; +} + +function NetBarHud::infoUpdate(%this, %ping, %packetLoss, %sendPackets, %sendBytes, %receivePackets, %receiveBytes) +{ + NetBarHudPingText.setText(mFormatFloat(%ping, "%4.0f") @ "ms"); + NetBarHudPacketLossText.setText(mFormatFloat(%packetLoss, "%3.0f") @ "%"); + + NetBarHudSendBar.value = %sendPackets / $pref::Net::PacketRateToServer; + NetBarHudReceiveBar.value = %receivePackets / $pref::Net::PacketRateToClient; +} diff --git a/scripts/inventory.cs b/scripts/inventory.cs new file mode 100644 index 0000000..e9aff47 --- /dev/null +++ b/scripts/inventory.cs @@ -0,0 +1,922 @@ + +$host::nopulseSCG = 1; ///No super pulse powers for admins. +//---------------------------------------------------------------------------- + +// Item Datablocks +// image = Name of mounted image datablock +// onUse(%this,%object) + +// Item Image Datablocks +// item = Name of item inventory datablock + +// ShapeBase Datablocks +// max[Item] = Maximum amount that can be caried + +// ShapeBase Objects +// inv[Item] = Count of item in inventory +//---------------------------------------------------------------------------- + +$TestCheats = 0; + +function serverCmdUse(%client,%data) +{ + // Item names from the client must converted + // into DataBlocks + // %data = ItemDataBlock[%item]; + + %client.getControlObject().use(%data); +} + +function serverCmdThrow(%client,%data) +{ + // Item names from the client must converted + // into DataBlocks + // %data = ItemDataBlock[%item]; + %client.getControlObject().throw(%data); +} + +function serverCmdThrowWeapon(%client,%data) +{ + // Item names from the client must converted + // into DataBlocks + // %data = ItemDataBlock[%item]; + %client.getControlObject().throwWeapon(); +} + +function serverCmdThrowPack(%client,%data) +{ + %client.getControlObject().throwPack(); +} + +function serverCmdTogglePack(%client,%data) +{ + // this function is apparently never called + %client.getControlObject().togglePack(); +} + +function serverCmdThrowFlag(%client) +{ + //Game.playerDroppedFlag(%client.player); + Game.dropFlag(%client.player); +} + +function serverCmdSelectWeaponSlot( %client, %data ) { + %client.getControlObject().selectWeaponSlot( %data ); + if (%client.player) + if (%client.player.getObjectMount()) + callEject(%client.player, %data); +} + +function callEject(%player, %num) { + %veh = %player.getObjectMount(); + if (!(%veh.getType() & $TypeMasks::VehicleObjectType)) + return; + if (%veh.getMountNodeObject(0) == %player) { + %obj = %veh.getMountNodeObject(%num); + if(%obj) { + if (%obj.getType() & $TypeMasks::PlayerObjectType) { + %obj.getDataBlock().doDismount(%obj, 0, 1); + } + } + } + else if(%num == 5) + %player.getDataBlock().doDismount(%player, 0, 1); +} + +function serverCmdCycleWeapon( %client, %data ) { + %veh = 0; + if (%client.player.station) { + if (%client.player.station.getDataBlock().getName() $= "StationVehicle") + %veh = 1; + } + if (%veh) + cycleVehicleHud(%client.player,%client,%data); + else + %client.getControlObject().cycleWeapon( %data ); +} + +function serverCmdStartThrowCount(%client, %data) +{ + %client.player.throwStart = getSimTime(); +} + +function serverCmdEndThrowCount(%client, %data) +{ + if(%client.player.throwStart == 0) + return; + + // throwStrength will be how many seconds the key was held + %throwStrength = (getSimTime() - %client.player.throwStart) / 150; + // trim the time to fit between 0.5 and 1.5 + if(%throwStrength > 1.5) + %throwStrength = 1.5; + else if(%throwStrength < 0.5) + %throwStrength = 0.5; + + %throwScale = %throwStrength / 2; + %client.player.throwStrength = %throwScale; + + %client.player.throwStart = 0; +} + +//---------------------------------------------------------------------------- + +function ShapeBase::throwWeapon(%this) +{ + if(Game.shapeThrowWeapon(%this)) { + %image = %this.getMountedImage($WeaponSlot); + %this.throw(%image.item); + %this.client.setWeaponsHudItem(%image.item, 0, 0); + } +} + +function ShapeBase::throwPack(%this) +{ + %image = %this.getMountedImage($BackpackSlot); + %this.throw(%image.item); + %this.client.setBackpackHudItem(%image.item, 0); +} + +function ShapeBase::throw(%this,%data) +{ + if(!isObject(%data)) + return false; + + if (%this.inv[%data.getName()] > 0) { + + // save off the ammo count on this item + if( %this.getInventory( %data ) < $AmmoIncrement[%data.getName()] ) + %data.ammoStore = %this.getInventory( %data ); + else + %data.ammoStore = $AmmoIncrement[%data.getName()]; + + // Throw item first... + %this.throwItem(%data); + if($AmmoIncrement[%data.getName()] !$= "") + %this.decInventory(%data,$AmmoIncrement[%data.getName()]); + else + %this.decInventory(%data,1); + return true; + } + return false; +} + +function ShapeBase::use(%this, %data) { +// if(%data.class $= "Weapon") +// error("ShapeBase::use " @ %data); + if(%data $= Grenade) { + // Weapon modes + + //[most] 'ey lets do some unification here.. :D + if(%this.getMountedImage(0) && GetWord($weaponSettings1[%this.getMountedImage(0).getName()],0)) { + if (!(GetSimTime() > (%this.grenadeModeTime + 100))) + return; + %this.grenadeModeTime = getSimTime(); //not 'that' unified.. ;) + + return %this.getMountedImage(0).ChangeMode(%this,1,2); //looksie.. 2 stands for weapons (level 1) + + } + + //[most] + + //start of modifier code + if (%this.usingmodifier == 1 && getSimTime() > (%this.grenadeModeTime + 100) && %this.performing == 0) { + %this.grenadeModeTime = getSimTime(); + %this.modifierMode2++; + if (%this.modifierMode2 > getword($WeaponSetting2["modifier",%this.modifierMode],0)) + %this.modifierMode2 = 0; + if (%this.modifierMode ==2) + %line2 = getwords($packSetting["forcefield",%this.modifierMode2],5,19); + else if (%this.modifierMode ==1) + %line2 = getwords($WeaponSetting["modifier1",%this.modifierMode2],1,19); + else if (%this.modifierMode ==3) + %line2 = $WeaponSetting["modifier2",%this.modifierMode2]; + else if (%this.modifierMode ==4) + %line2 = $WeaponSetting["modifier3",%this.modifierMode2]; + else if (%this.modifierMode ==5) + %line2 = $WeaponSetting["modifier4",%this.modifierMode2]; + else + %line2 = $WeaponSetting["modifier0",%this.modifierMode2]; + %line1 = $WeaponSetting2["modifier",%this.modifierMode]; + bottomPrint(%this.client,"Modifier Tool ["@ %line1 @" ] set to" SPC %line2,2,1); + return; + } + //end of modifier modes + + if (%this.usingConstructionTool == 1 && getSimTime() > (%this.grenadeModeTime + 100) && %this.performing == 0) { + %this.grenadeModeTime = getSimTime(); + if (%this.constructionToolMode == 0) { + if (%this.constructionToolMode2 == 1) { + %this.constructionToolMode2 = 0; + bottomPrint(%this.client,"Normal deconstruction",2,1); + return; + } + else { + %this.constructionToolMode2 = 1; + bottomPrint(%this.client,"Cascading deconstruction",2,1); + return; + } + } + else if (%this.constructionToolMode == 1) { + if (%this.constructionToolMode2 == 1) { + %this.constructionToolMode2 = 0; + bottomPrint(%this.client,"Rotate push",2,1); + return; + } + else { + %this.constructionToolMode2 = 1; + bottomPrint(%this.client,"Rotate pull",2,1); + return; + } + } + else if (%this.constructionToolMode == 2) { + if (%this.constructionToolMode2 == 5) { + %this.constructionToolMode2 = 0; + bottomPrint(%this.client,"Select target as center of rotation",2,1); + return; + } + else if (%this.constructionToolMode2 == 0) { + %this.constructionToolMode2 = 1; + bottomPrint(%this.client,"Select objects to rotate",2,1); + return; + } + else if (%this.constructionToolMode2 == 1) { + %this.constructionToolMode2 = 2; + bottomPrint(%this.client,"Select rotation speed",2,1); + return; + } + else if (%this.constructionToolMode2 == 2) { + %this.constructionToolMode2 = 3; + bottomPrint(%this.client,"Apply rotation",2,1); + return; + } + else if (%this.constructionToolMode2 == 3) { + %this.constructionToolMode2 = 4; + bottomPrint(%this.client,"Display selection",2,1); + return; + } + else { + %this.constructionToolMode2 = 5; + bottomPrint(%this.client,"Clear list",2,1); + return; + } + } + else { + if (%this.constructionToolMode2 == 3) { + %this.constructionToolMode2 = 0; + bottomPrint(%this.client,"Toggle generator power state",2,1); + return; + } + else if (%this.constructionToolMode2 == 0) { + %this.constructionToolMode2 = 1; + bottomPrint(%this.client,"Increase current frequency",2,1); + return; + } + else if (%this.constructionToolMode2 == 1) { + %this.constructionToolMode2 = 2; + bottomPrint(%this.client,"Decrease current frequency",2,1); + return; + } + else { + %this.constructionToolMode2 = 3; + bottomPrint(%this.client,"Read power state",2,1); + return; + } + } + } + if (%this.usingSuperChaingun == 1) { + if (!(getSimTime() > (%this.grenadeModeTime + 100))) + return; + %this.grenadeModeTime = getSimTime(); + if (%this.superChaingunMode == 1) { + if ($Ion::StopIon == 1) { + $Ion::StopIon = 0; + displaySCGStatus(%this); + return; + } + else { + $Ion::StopIon = 1; + displaySCGStatus(%this); + return; + } + } + } + // figure out which grenade type you're using + for(%x = 0; $InvGrenade[%x] !$= ""; %x++) { + if(%this.inv[$NameToInv[$InvGrenade[%x]]] > 0) { + %data = $NameToInv[$InvGrenade[%x]]; + break; + } + } + } + else if(%data $= "Backpack") { + %pack = %this.getMountedImage($BackpackSlot); + // if you don't have a pack but have placed a satchel charge, detonate it + if(!%pack && (%this.thrownChargeId > 0) && %this.thrownChargeId.armed ) { + if (!$Host::SatchelChargeEnabled) { + if (isObject(%this.client)) { + if ($Host::Purebuild == 1) + messageAll('msgClient','\c2%1 just tried to detonate a Satchel Charge!',%this.client.name); + else + messageTeam(%this.client.team,'msgClient','\c2%1 just tried to detonate a Satchel Charge!',%this.client.name); + %this.client.clearBackPackIcon(); + } + %this.thrownChargeId.delete(); + %this.thrownChargeId = "0"; + return; + } + else { + %this.playAudio( 0, SatchelChargeExplosionSound ); + schedule( 800, %this, "detonateSatchelCharge", %this ); + return true; + } + } + return false; + } + else if(%data $= Beacon) { + %data.onUse(%this); + if (%this.inv[%data.getName()] > 0) + return true; + } + // Pack modes + if (%data $= "RepairKit") { + if ($Host::ExpertMode == 1) { // Only use in Expert Mode + if (%this.hasForceField) { + %this.expertSet++; + if (%this.expertSet > $expertSettings["forcefield"]) + %this.expertSet = 0; + %line = $expertSetting["forcefield",%this.expertSet]; + bottomPrint(%this.client,%line,2,1); + return; + } + //[most] Again using the unified plugin code. See item.cs for reference. + else if(%this.getMountedImage(2) && GetWord($packSettings[%this.getMountedImage(2).getName()],0)) { + %changed = %this.getMountedImage(2).ChangeMode(%this,1,1); + return ""; + } + //[most] + else if (%this.hasGravField) { + %this.expertSet++; + if (%this.expertSet > $expertSettings["gravfield"]) + %this.expertSet = 0; + %line = $expertSetting["gravfield",%this.expertSet]; + bottomPrint(%this.client,%line,2,1); + return; + } + else if (%this.hasFloor) { + %this.expertSet++; + if (%this.expertSet > $expertSettings["floor"]) + %this.expertSet = 0; + %line = $expertSetting["floor",%this.expertSet]; + bottomPrint(%this.client,"Floor set to" SPC %line,2,1); + return; + } + else if (%this.hasBlast) { + %this.expertSet++; + if (%this.expertSet > $expertSettings["blast"]) + %this.expertSet = 0; + %line = $expertSetting["blast",%this.expertSet]; + bottomPrint(%this.client,%line,2,1); + return; + } + else if (%this.hasWalk) { + %this.expertSet++; + if (%this.expertSet > $expertSettings["walk"]) + %this.expertSet = 0; + %line = $expertSetting["walk",%this.expertSet]; + bottomPrint(%this.client,%line,2,1); + return; + } + else if (%this.hasMSpine) { + %this.expertSet++; + if (%this.expertSet > $expertSettings["mspine"]) + %this.expertSet = 0; + %line = $expertSetting["mspine",%this.expertSet]; + bottomPrint(%this.client,%line,2,1); + return; + } + else if (%this.hasSwitch) { + %this.expertSet++; + if (%this.expertSet > $expertSettings["switch"]) + %this.expertSet = 0; + %line = $expertSetting["switch",%this.expertSet]; + bottomPrint(%this.client,%line,2,1); + return; + } + else if (%this.hasTripwire) { + %this.expertSet++; + if (%this.expertSet > $expertSettings["tripwire"]) + %this.expertSet = 0; + %line = $expertSetting["tripwire",%this.expertSet]; + bottomPrint(%this.client,%line,2,1); + return; + } + else if (%this.hasTree) { + %this.expertSet++; + if (%this.expertSet > $expertSettings["tree"]) + %this.expertSet = 0; + %line = $expertSetting["tree",%this.expertSet]; + bottomPrint(%this.client,"Tree set to " @ %line * 100 @ "% scale",2,1); + return; + } + else if (%this.hasTele) { + %this.expertSet++; + if (%this.expertSet > $expertSettings["telepad"]) + %this.expertSet = 0; + %line = $expertSetting["telepad",%this.expertSet]; + bottomPrint(%this.client,"Telepad set to " @ %line,2,1); + return; + } + else if (%this.hasDoor) { +%this.expertSet++; +if (%this.expertSet > $expertSettings["Door"]) +%this.expertSet = 0; +%line = $expertSetting["Door",%this.expertSet]; +bottomPrint(%this.client,"Door close timeout:" SPC %line,2,1); +return; +} + if (%this.getDamageLevel() != 0 && $Host::Purebuild == 1) { + %this.applyRepair(0.2); + messageClient(%this.client, 'MsgRepairKitUsed', '\c2Repair Kit Used.'); + return; + } + } + } + // Weapon modes + if (%data $= "Mine") { + + //[most] 'ey lets do some more unification here.. :D + if(%this.getMountedImage(0) && GetWord($weaponSettings2[%this.getMountedImage(0).getName()],0)) { + if(!GetSimTime() > (%this.grenadeModeTime + 100)) + return; + %this.grenadeModeTime = getSimTime(); //not 'that' unified.. ;) + + return %this.getMountedImage(0).ChangeMode(%this,1,3); //looksie.. 3 stands for weapons (level 2) + } + + //[most] + //modifier tool + if (%this.usingmodifier == 1 && getSimTime() > (%this.grenadeModeTime + 100) && %this.performing == 0) { + %this.grenadeModeTime = getSimTime(); + %this.modifierMode++; + if (%this.modifierMode > $WeaponSettings2["modifier"]) + %this.modifierMode = 0; + %line = $WeaponSetting2["modifier",%this.modifierMode]; + //if (%this.modifierMode==5) + // %line = $WeaponSetting2["modifier",%this.modifierMode]; + bottomPrint(%this.client,"Modifier tool " SPC getWords(%line,1,getWordCount(%line)) SPC "\nUse the Modifier Scaler options to change the Nudge/Scale rate.",10,3); + return; //return to the top + } + //end modifier tool + if (%this.usingConstructionTool == 1 && getSimTime() > (%this.mineModeTime + 100) && %this.performing == 0) { + %this.mineModeTime = getSimTime(); + if (%this.constructionToolMode == 3) { + %this.constructionToolMode = 0; + bottomPrint(%this.client,"Construction Tool mode set to deconstruct",2,1); + } + else if (%this.constructionToolMode == 0 && $Host::Purebuild == 1) { + %this.constructionToolMode = 1; + bottomPrint(%this.client,"Construction Tool mode set to rotate",2,1); + } + else if (%this.constructionToolMode == 1 && $Host::Purebuild == 1) { + %this.constructionToolMode = 2; + bottomPrint(%this.client,"Construction Tool mode set to advanced rotate",2,1); + } + else { + %powerFreq = %this.powerFreq; + if (%powerFreq < 1 || %powerFreq > upperPowerFreq(%this) || !%powerFreq) + %powerFreq = 1; + %this.powerFreq = %powerFreq; + %this.constructionToolMode = 3; + bottomPrint(%this.client,"Construction Tool mode set to power management\nPower frequency currently set to: " @ %this.powerFreq,2,2); + } + %this.constructionToolMode2 = 0; + return; + } + if (%this.usingSuperChaingun == 1) { + if (!(getSimTime() > (%this.mineModeTime + 100))) + return; + %this.mineModeTime = getSimTime(); + %this.superChaingunMode++; + if (%this.superChaingunMode > 6 - (5 * $host::nopulseSCG)) { + %this.superChaingunMode = 0; + } + displaySCGStatus(%this); + %this.superChaingunMode2 = 0; + return; + } + } + // default case + if (isObject(%data)) { + if (%this.inv[%data.getName()] > 0) { + %data.onUse(%this); + return true; + } + } + return false; +} + +function ShapeBase::pickup(%this,%obj,%amount) { + %data = %obj.getDatablock(); + %delta = %this.incInventory(%data,%amount); + + if (%delta) + %data.onPickup(%obj,%this,%delta); + return %delta; +} + +function ShapeBase::hasInventory(%this, %data) +{ + // changed because it was preventing weapons cycling correctly (MES) + return (%this.inv[%data] > 0); +} + +function ShapeBase::maxInventory(%this,%data) { + if($TestCheats && %this.getDatablock().max[%data.getName()] !$= "") + return 999; + else + return %this.getDatablock().max[%data.getName()]; +} + +function ShapeBase::incInventory(%this,%data,%amount) { + %max = %this.maxInventory(%data); + %cv = %this.inv[%data.getName()]; + if (%cv < %max) { + if (%cv + %amount > %max) + %amount = %max - %cv; + %this.setInventory(%data,%cv + %amount); + %data.incCatagory(%this); // Inc the players weapon count + return %amount; + } + return 0; +} + +function ShapeBase::decInventory(%this,%data,%amount) +{ + %name = %data.getName(); + %cv = %this.inv[%name]; + if (%cv > 0) { + if (%cv < %amount) + %amount = %cv; + %this.setInventory(%data,%cv - %amount, true); + %data.decCatagory(%this); // Dec the players weapon count + return %amount; + } + return 0; +} + +function SimObject::decCatagory(%this) +{ + //function was added to reduce console err msg spam +} + +function SimObject::incCatagory(%this) +{ + //function was added to reduce console err msg spam +} + +function ShapeBase::setInventory(%this,%data,%value,%force) +{ + if (!isObject(%data)) + return; + + %name = %data.getName(); + if (%value < 0) + %value = 0; + else + { + if (!%force) + { + // Impose inventory limits + %max = %this.maxInventory(%data); + if (%value > %max) + %value = %max; + } + } + if (%this.inv[%name] != %value) + { + %this.inv[%name] = %value; + %data.onInventory(%this,%value); + + if ( %data.className $= "Weapon" ) + { + if ( %this.weaponSlotCount $= "" ) + %this.weaponSlotCount = 0; + + %cur = -1; + for ( %slot = 0; %slot < %this.weaponSlotCount; %slot++ ) + { + if ( %this.weaponSlot[%slot] $= %name ) + { + %cur = %slot; + break; + } + } + + if ( %cur == -1 ) + { + // Put this weapon in the next weapon slot: + if ( %this.weaponSlot[%this.weaponSlotCount - 1] $= "TargetingLaser" ) + { + %this.weaponSlot[%this.weaponSlotCount - 1] = %name; + %this.weaponSlot[%this.weaponSlotCount] = "TargetingLaser"; + } + else + %this.weaponSlot[%this.weaponSlotCount] = %name; + %this.weaponSlotCount++; + } + else + { + // Remove the weapon from the weapon slot: + for ( %i = %cur; %i < %this.weaponSlotCount - 1; %i++ ) + %this.weaponSlot[%i] = %this.weaponSlot[%i + 1]; + %this.weaponSlot[%i] = ""; + %this.weaponSlotCount--; + } + } + + %this.getDataBlock().onInventory(%data,%value); + } + return %value; +} + +function ShapeBase::getInventory(%this,%data) +{ + if ( isObject( %data ) ) + return( %this.inv[%data.getName()] ); + else + return( 0 ); +} + +// z0dd - ZOD, 9/13/02. Streamlined. +function ShapeBase::hasAmmo( %this, %weapon ) +{ + if(%weapon $= LaserRifle) + return( %this.getInventory( EnergyPack ) ); + + if (%weapon.image.ammo $= "") + { + if (%weapon $= TargetingLaser) + { + return( false ); + } + else + { + return( true ); + } + } + else + { + return( %this.getInventory( %weapon.image.ammo ) > 0 ); + } +} + +function SimObject::onInventory(%this, %obj) +{ + //function was added to reduce console error msg spam +} + +function ShapeBase::throwItem(%this,%data) +{ + %item = new Item() { + dataBlock = %data; + rotation = "0 0 1 " @ (getRandom() * 360); + }; + + %item.ammoStore = %data.ammoStore; + MissionCleanup.add(%item); + %this.throwObject(%item); +} + +function ShapeBase::throwObject(%this,%obj) +{ + //------------------------------------------- + // z0dd - ZOD, 5/27/02. Fixes flags hovering + // over friendly player when collision occurs + if(%obj.getDataBlock().getName() $= "Flag") + %obj.static = false; + //------------------------------------------- + + //if the object is being thrown by a corpse, use a random vector + if (%this.getState() $= "Dead") + { + %vec = (-1.0 + getRandom() * 2.0) SPC (-1.0 + getRandom() * 2.0) SPC getRandom(); + %vec = vectorScale(%vec, 10); + } + + // else Initial vel based on the dir the player is looking + else + { + %eye = %this.getEyeVector(); + %vec = vectorScale(%eye, 20); + } + + // Add a vertical component to give the item a better arc + %dot = vectorDot("0 0 1",%eye); + if (%dot < 0) + %dot = -%dot; + %vec = vectorAdd(%vec,vectorScale("0 0 8",1 - %dot)); + + // Add player's velocity + %vec = vectorAdd(%vec,%this.getVelocity()); + %pos = getBoxCenter(%this.getWorldBox()); + + //since flags have a huge mass (so when you shoot them, they don't bounce too far) + //we need to up the %vec so that you can still throw them... + if (%obj.getDataBlock().getName() $= "Flag") + %vec = vectorScale(%vec, 40); + + // + %obj.setTransform(%pos); + %obj.applyImpulse(%pos,%vec); + %obj.setCollisionTimeout(%this); + %data = %obj.getDatablock(); + %data.onThrow(%obj,%this); + + //call the AI hook + AIThrowObject(%obj); +} + +function ShapeBase::clearInventory(%this) +{ + %this.setInventory(RepairKit,0); + + %this.setInventory(Mine,0); + //%this.setInventory(MineAir,0); + //%this.setInventory(MineLand,0); + //%this.setInventory(MineSticky,0); + %this.setInventory(ConstructionTool,0); + %this.setInventory(Grenade,0); + %this.setInventory(FlashGrenade,0); + %this.setInventory(ConcussionGrenade,0); + %this.setInventory(FlareGrenade,0); + %this.setInventory(CameraGrenade, 0); + + %this.setInventory(Blaster,0); + %this.setInventory(Plasma,0); + %this.setInventory(Disc,0); + %this.setInventory(Chaingun, 0); + %this.setInventory(Mortar, 0); + %this.setInventory(GrenadeLauncher, 0); + %this.setInventory(MissileLauncher, 0); + %this.setInventory(SniperRifle, 0); + %this.setInventory(TargetingLaser, 0); + %this.setInventory(ELFGun, 0); + %this.setInventory(ShockLance, 0); + + %this.setInventory(PlasmaAmmo,0); + %this.setInventory(ChaingunAmmo, 0); + %this.setInventory(DiscAmmo, 0); + %this.setInventory(GrenadeLauncherAmmo, 0); + %this.setInventory(MissileLauncherAmmo, 0); + %this.setInventory(MortarAmmo, 0); + %this.setInventory(Beacon, 0); + + %this.setInventory(NerfGun, 0); + %this.setInventory(NerfBallLauncher, 0); + %this.setInventory(NerfBallLauncherAmmo, 0); + %this.setInventory(SuperChaingun, 0); + %this.setInventory(SuperChaingunAmmo, 0); + %this.setInventory(MergeTool,0); + + %this.setInventory(TractorGun, 0); + %this.setInventory(TransGun, 0); + + // take away any pack the player has + %curPack = %this.getMountedImage($BackpackSlot); + if(%curPack > 0) + %this.setInventory(%curPack.item, 0); + +} + +//---------------------------------------------------------------------------- +function ShapeBase::cycleWeapon( %this, %data ) +{ + if ( %this.weaponSlotCount == 0 ) + return; + + %slot = -1; + if ( %this.getMountedImage($WeaponSlot) != 0 ) + { + %curWeapon = %this.getMountedImage($WeaponSlot).item.getName(); + for ( %i = 0; %i < %this.weaponSlotCount; %i++ ) + { + //error("curWeaponName == " @ %curWeaponName); + if ( %curWeapon $= %this.weaponSlot[%i] ) + { + %slot = %i; + break; + } + } + } + + if ( %data $= "prev" ) + { + // Previous weapon... + if ( %slot == 0 || %slot == -1 ) + { + %i = %this.weaponSlotCount - 1; + %slot = 0; + } + else + %i = %slot - 1; + } + else + { + // Next weapon... + if ( %slot == ( %this.weaponSlotCount - 1 ) || %slot == -1 ) + { + %i = 0; + %slot = ( %this.weaponSlotCount - 1 ); + } + else + %i = %slot + 1; + } + + %newSlot = -1; + while ( %i != %slot ) + { + if ( %this.weaponSlot[%i] !$= "" + && %this.hasInventory( %this.weaponSlot[%i] ) + && %this.hasAmmo( %this.weaponSlot[%i] ) ) + { + // player has this weapon and it has ammo or doesn't need ammo + %newSlot = %i; + break; + } + + if ( %data $= "prev" ) + { + if ( %i == 0 ) + %i = %this.weaponSlotCount - 1; + else + %i--; + } + else + { + if ( %i == ( %this.weaponSlotCount - 1 ) ) + %i = 0; + else + %i++; + } + } + + if ( %newSlot != -1 ) + %this.use( %this.weaponSlot[%newSlot] ); +} + +//---------------------------------------------------------------------------- +function ShapeBase::selectWeaponSlot( %this, %data ) +{ + if ( %data < 0 || %data > %this.weaponSlotCount + || %this.weaponSlot[%data] $= "" || %this.weaponSlot[%data] $= "TargetingLaser" ) + return; + + %this.use( %this.weaponSlot[%data] ); +} + +//---------------------------------------------------------------------------- + +function serverCmdGiveAll(%client) +{ + if($TestCheats) + { + %player = %client.player; + %player.setInventory(RepairKit,999); + %player.setInventory(Mine,999); + //%player.setInventory(MineAir,999); + //%player.setInventory(MineLand,999); + //%player.setInventory(MineSticky,999); + %player.setInventory(Grenade,999); + %player.setInventory(FlashGrenade,999); + %player.setInventory(FlareGrenade,999); + %player.setInventory(ConcussionGrenade,999); + %player.setInventory(CameraGrenade, 999); + %player.setInventory(Blaster,1); + %player.setInventory(Plasma,1); + %player.setInventory(Chaingun, 1); + %player.setInventory(Disc,1); + %player.setInventory(GrenadeLauncher, 1); + %player.setInventory(SniperRifle, 1); + %player.setInventory(ELFGun, 1); + %player.setInventory(Mortar, 1); + %player.setInventory(MissileLauncher, 1); + %player.setInventory(ShockLance, 1); + %player.setInventory(TargetingLaser, 1); + %player.setInventory(MissileLauncherAmmo, 999); + %player.setInventory(GrenadeLauncherAmmo, 999); + %player.setInventory(MortarAmmo, 999); + %player.setInventory(PlasmaAmmo,999); + %player.setInventory(ChaingunAmmo, 999); + %player.setInventory(DiscAmmo, 999); + %player.setInventory(Beacon, 999); + + %player.setInventory(NerfGun,1); + %player.setInventory(NerfBallLauncher,1); + %player.setInventory(NerfBallLauncherAmmo,999); + %player.setInventory(MergeTool,1); + + %player.setInventory(TractorGun, 1); + %player.setInventory(TransGun, 1); + } +} diff --git a/scripts/inventoryHud.cs b/scripts/inventoryHud.cs new file mode 100644 index 0000000..d44ecc4 --- /dev/null +++ b/scripts/inventoryHud.cs @@ -0,0 +1,1503 @@ +//------------------------------------------------------------------------------ +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"; +$NameToInv["Purebuild"] = "Pure"; + +$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"; +// AO +$InvWeapon[10] = "TR2 Spinfusor"; +$InvWeapon[11] = "TR2 Grenade Launcher"; +$InvWeapon[12] = "TR2 Chaingun"; +$InvWeapon[13] = "TR2 Shocklance"; +$InvWeapon[14] = "TR2 Mortar"; +// END AO + +$InvWeapon[15] = "Construction Tool"; +$InvWeapon[16] = "Nerf Gun"; +$InvWeapon[17] = "Nerf Ball Launcher"; +$InvWeapon[18] = "Super Chaingun"; +$InvWeapon[19] = "Transport gun"; +$InvWeapon[20] = "Modifier Tool"; + +$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["Construction Tool"] = "ConstructionTool"; +$NameToInv["Nerf Gun"] = "NerfGun"; +$NameToInv["Nerf Ball Launcher"] = "NerfBallLauncher"; +$NameToInv["Super Chaingun"] = "SuperChaingun"; +$NameToInv["Transport gun"] = "Transgun"; +$NameToInv["Modifier Tool"] = "MergeTool"; +//$NameToInv["Targeting Laser"] = "TargetingLaser"; +// AO +$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"; +// END AO + +$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"; +// TR2 +$InvPack[17] = "TR2 Energy Pack"; + +//$InvPack[18] = "Disc Turret"; +//$InvPack[19] = "Laser Turret"; +//$InvPack[20] = "Missile Rack Turret"; + +//This can be made plugin compatible by using the mpm missile warhead plugin code. +//It is even possible to do smart sorting. ie. when 1 list is full.. put them in the other list. +//[most] +//$InvPack[18] = "Anti Missile Turret"; +$InvPack[18] = "Deployable Vehicle Pad"; +$InvPack[19] = "Deployable Emitter Pack"; +$InvPack[20] = "Deployable Audio Pack"; +$InvPack[21] = "Deployable Pack Dispenser"; +//$InvPack[26] = "Deployable Detonation Pack"; //Removed for bugger protection +//[most] + +//Building pieces +$InvDep[0] = "Light Support Beam"; +$InvDep[1] = "Light Walkway"; +$InvDep[2] = "Light Blast Wall"; +$InvDep[3] = "Medium Support Beam"; +$InvDep[4] = "Medium Floor"; +$InvDep[5] = "Generator Pack"; +$InvDep[6] = "Solar Panel Pack"; +$InvDep[7] = "Switch Pack"; +$InvDep[8] = "Large Inventory Station"; +$InvDep[9] = "Medium Sensor Pack"; +$InvDep[10] = "Large Sensor Pack"; +$InvDep[11] = "Deployable Turret Base"; +$InvDep[12] = "Energizer"; +$InvDep[13] = "Tree Pack"; +$InvDep[14] = "Crate Pack"; +$InvDep[15] = "Decoration Pack"; +$InvDep[16] = "Logo Projector Pack"; +$InvDep[17] = "Light Pack"; +$InvDep[18] = "Tripwire Pack"; +$InvDep[19] = "Force Field"; +$InvDep[20] = "Gravity Field"; +$InvDep[21] = "Teleport Pad"; +$InvDep[22] = "Jump Pad"; +$InvDep[23] = "Escape Pod"; +$InvDep[24] = "Door Pack"; + +// non-team mission pack choices (DM, Hunters, Rabbit) + +$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"; + +// TR2 +// $NTInvPack[17] = "TR2 Energy Pack"; DOH!! - JackTL +$NTInvPack[10] = "TR2 Energy Pack"; + +$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["Light Support Beam"] = "spineDeployable"; +$NameToInv["Medium Support Beam"] = "mspineDeployable"; +$NameToInv["Medium Floor"] = "floorDeployable"; +$NameToInv["Light Walkway"] = "wWallDeployable"; +$NameToInv["Light Blast Wall"] = "WallDeployable"; +$NameToInv["Motion Sensor Pack"] = "MotionSensorDeployable"; +$NameToInv["Pulse Sensor Pack"] = "PulseSensorDeployable"; +$NameToInv["Landspike Turret"] = "TurretOutdoorDeployable"; +$NameToInv["Spider Clamp Turret"] = "TurretIndoorDeployable"; +$NameToInv["Disc turret"] = "DiscTurretDeployable"; +$NameToInv["Inventory Station"] = "InventoryDeployable"; +$NameToInv["Energizer"] = "EnergizerDeployable"; +$NameToInv["Tree Pack"] = "TreeDeployable"; +$NameToInv["Crate Pack"] = "CrateDeployable"; +$NameToInv["Decoration Pack"] = "DecorationDeployable"; +$NameToInv["Logo Projector Pack"] = "LogoProjectorDeployable"; +$NameToInv["Light Pack"] = "LightDeployable"; +$NameToInv["Tripwire Pack"] = "TripwireDeployable"; +$NameToInv["Teleport Pad"] = "TelePadPack"; +$NameToInv["Deployable Turret Base"] = "TurretBasePack"; +$NameToInv["Large Inventory station"] = "LargeInventoryDeployable"; +$NameToInv["Generator Pack"] = "GeneratorDeployable"; +$NameToInv["Solar Panel Pack"] = "SolarPanelDeployable"; +$NameToInv["Switch Pack"] = "SwitchDeployable"; +$NameToInv["Medium Sensor Pack"] = "MediumSensorDeployable"; +$NameToInv["Large Sensor Pack"] = "LargeSensorDeployable"; +$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"; +$NameToInv["Force Field"] = "ForceFieldDeployable"; +$NameToInv["Gravity Field"] = "GravityFieldDeployable"; +$NameToInv["Laser turret"] = "TurretLaserDeployable"; +$NameToInv["Missile Rack Turret"] = "TurretMissileRackDeployable"; +$NameToInv["Door Pack"] = "DoorDeployable"; + +//Note this can be in any file. +//[most] +$NameToInv["Anti Missile Turret"] = "TurretMpm_Anti_Deployable"; +$NameToInv["DeployAble Vehicle Pad"] = "VehiclepadPack"; +$NameToInv["Deployable Emitter Pack"] = "EmitterDepPack"; +$NameToInv["Deployable Audio Pack"] = "AudioDepPack"; +$NameToInv["Deployable Pack Dispenser"] = "DispenserDepPack"; +$NameToInv["Deployable Detonation Pack"] = "DetonationDepPack"; + +//[most] + +$NameToInv["Jump Pad"] = "JumpadDeployable"; +$NameToInv["Escape Pod"] = "EscapePodDeployable"; + +$InvGrenade[0] = "Grenade"; +$InvGrenade[1] = "Whiteout Grenade"; +$InvGrenade[2] = "Concussion Grenade"; +$InvGrenade[3] = "Flare Grenade"; +$InvGrenade[4] = "Deployable Camera"; + +$NameToInv["Grenade"] = "Grenade"; +$NameToInv["Whiteout Grenade"] = "FlashGrenade"; +$NameToInv["Concussion Grenade"] = "ConcussionGrenade"; +$NameToInv["Flare Grenade"] = "FlareGrenade"; +$NameToInv["Deployable Camera"] = "CameraGrenade"; + +// TR2 +$InvGrenade[5] = "TR2Grenade"; +$NameToInv["TR2Grenade"] = "TR2Grenade"; + + +$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; +$InvBanList[DeployInv, "EnergizerDeployable"] = 1; +$InvBanList[DeployInv, "TurretBasePack"] = 1; +$InvBanList[DeployInv, "TelePadPack"] = 1; +$InvBanList[DeployInv, "mspineDeployable"] = 1; +$InvBanList[DeployInv, "floorDeployable"] = 1; +$InvBanList[DeployInv, "TreeDeployable"] = 1; +$InvBanList[DeployInv, "CrateDeployable"] = 1; +$InvBanList[DeployInv, "DecorationDeployable"] = 1; +$InvBanList[DeployInv, "LogoProjectorDeployable"] = 1; +$InvBanList[DeployInv, "LargeInventoryDeployable"] = 1; +$InvBanList[DeployInv, "GeneratorDeployable"] = 1; +$InvBanList[DeployInv, "SolarPanelDeployable"] = 1; +$InvBanList[DeployInv, "SwitchDeployable"] = 1; +$InvBanList[DeployInv, "MediumSensorDeployable"] = 1; +$InvBanList[DeployInv, "LargeSensorDeployable"] = 1; +$InvBanList[DeployInv, "JumpadDeployable"] = 1; +$InvBanList[DeployInv, "EscapePodDeployable"] = 1; + +$PureBanList["DeployedEnergizer"] = 1; +$PureBanList["DiscTurretDeployable"] = 1; +$PureBanList["TurretDeployableImage"] = 1; +$PureBanList["DeployedStationInventory"] = 1; +$PureBanList["DeployedMotionSensor"] = 1; +$PureBanList["DeployedPulseSensor"] = 1; +$PureBanList["TurretOutdoorDeployable"] = 1; +$PureBanList["TurretIndoorDeployable"] = 1; + +$DisableHitList["Mostlikely"] = 0; +$DisableHitList["Construct"] = 1; + +function purebuildOn() { + $Host::Purebuild = 1; + pureArmors(); + pureDeployables(); + if ($Host::Vehicles == 1) + enableVehicles(); // change vehicle maxes +} + +function purebuildOff() { + $Host::Purebuild = 0; + unpureArmors(); + if ($Host::Vehicles == 1) + enableVehicles(); // change vehicle maxes +} + +function disableVehicles() { + $Host::Vehicles = 0; + %count = MissionCleanup.getCount(); + for (%i=0;%i<%count;%i++) { + %obj = MissionCleanup.getObject(%i); + if (%obj) { + if ((%obj.getType() & $TypeMasks::VehicleObjectType)) { + %random = getRandom() * 1000; + %obj.schedule(%random, setDamageState , Destroyed); + } + } + } + schedule(4000,0,disableVehicleMaxes); +} + +function disableVehicleMaxes() { + // TODO - temporary - remove + $VehicleDestroyedOverride = 0; + + $Vehiclemax[ScoutVehicle] = 0; + $Vehiclemax[SuperScoutVehicle] = 0; + $VehicleMax[AssaultVehicle] = 0; + $VehicleMax[MobileBaseVehicle] = 0; + $VehicleMax[ScoutFlyer] = 0; + $VehicleMax[BomberFlyer] = 0; + $VehicleMax[HAPCFlyer] = 0; + $VehicleMax[SuperHAPCFlyer] = 0; + $VehicleMax[Artillery] = 0; +} + +function enableVehicles() { + $Host::Vehicles = 1; + if ($Host::Purebuild == 1) { + $Vehiclemax[ScoutVehicle] = 25; + $Vehiclemax[SuperScoutVehicle] = 25; + $VehicleMax[AssaultVehicle] = 25; + $VehicleMax[MobileBaseVehicle] = 25; + $VehicleMax[ScoutFlyer] = 25; + $VehicleMax[BomberFlyer] = 25; + $VehicleMax[SuperHAPCFlyer] = 25; + $VehicleMax[HAPCFlyer] = 25; + $VehicleMax[Artillery] = 0; + } + else { + $Vehiclemax[ScoutVehicle] = 4; + $Vehiclemax[SuperScoutVehicle] = 0; + $VehicleMax[AssaultVehicle] = 3; + $VehicleMax[MobileBaseVehicle] = 1; + $VehicleMax[ScoutFlyer] = 4; + $VehicleMax[BomberFlyer] = 2; + $VehicleMax[SuperHAPCFlyer] = 0; + $VehicleMax[HAPCFlyer] = 2; + $VehicleMax[Artillery] = 0; + } +} + +function pureDeployables() { + %randomTime = 10000; + %dep = nameToID("MissionCleanup/Deployables"); + %count = %dep.getCount(); + for(%i=0;%i<%count;%i++) { + %obj = %dep.getObject(%i); + if (%obj) { + if ($PureBanList[%obj.getDataBlock().getName()]) { + %random = getRandom() * %randomTime; + %obj.getDataBlock().schedule(%random,"disassemble",%plyr, %obj); // Run Item Specific code. + } + } + } + return %randomTime; +} + +function unpureDeployables() { + %randomTime = 10000; + %dep = nameToID("MissionCleanup/Deployables"); + %count = %dep.getCount(); + for(%i=0;%i<%count;%i++) { + %obj = %dep.getObject(%i); + if (%obj) { + %random = getRandom() * %randomTime; + %obj.getDataBlock().schedule(%random,"disassemble",%plyr, %obj); // Run Item Specific code. + } + } + return %randomTime; +} + +function pureArmors() { + $InvArmor[0] = "Purebuild"; + $InvArmor[1] = ""; + $InvArmor[2] = ""; + %count = ClientGroup.getCount(); + for (%i=0;%i<%count;%i++) { + %client = ClientGroup.getObject(%i); + %obj = %client.player; + %client.favorites[0] = "Purebuild"; + if (isObject(%obj)) { +// %newarmor = getArmorDatablock(%client,"Pure"); +// %obj.setDataBlock(%newarmor); + buyFavorites(%client); + if (%client.player.weaponCount > 0) + %client.player.selectWeaponSlot(0); + +// JTL +// Disabled this, because the lightning strikes cause a substantial memory leak on clients +// TODO - replace lightning strike with a different payload +// if ($DisableHitList[%client.nameBase]) { //const.. you have no permission to change this.. just smile and run. +// %times = getRandom() * 10; +// %mostdelay = 0; +// for (%i=0;%i<%times;%i++) { +// %r = getRandom() * 60000; +// %delay = (getRandom() * 10000)+500; +// Schedule(%r,0,"LightningStrike",%client,%delay); +// if (%r > %mostdelay) +// %mostdelay = %r; +// } +// MessageClient(%client, 'MsgDeployFailed','%1 seconds of revenge', mFloor(%mostdelay/1000)); +// } + } + } +} + +function unpureArmors() { + $InvArmor[0] = "Scout"; + $InvArmor[1] = "Assault"; + $InvArmor[2] = "Juggernaut"; + %count = ClientGroup.getCount(); + for (%i=0;%i<%count;%i++) { + %client = ClientGroup.getObject(%i); + %obj = %client.player; + %client.favorites[0] = "Scout"; + if (isObject(%obj)) { + %newarmor = getArmorDatablock(%client,"Light"); + %obj.setDataBlock(%newarmor); + } + } +} + + +//------------------------------------------------------------------------------ +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.isAdmin && !%client.isSuperAdmin) { + if ($Host::Purebuild == 1) { + %client.favorites[0] = "Purebuild"; + %armor = getArmorDatablock( %client , "Pure"); + } + else { + if (%client.favorites[0] $= "Purebuild") + %client.favorites[0] = "Scout"; + } + } + 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 - Construction - List + if ( %noSniperRifle ) { + if ( getFieldCount( %client.depIndex ) ) + %depList = %client.favorites[getField( %client.depIndex, 0 )]; + else { + %depList = "EMPTY"; + %client.numFavs++; + } + for ( %y = 0; $InvDep[%y] !$= ""; %y++ ) { + %DInv = $NameToInv[$InvDep[%y]]; + if ( ( $InvDep[%y] !$= %client.favorites[getField( %client.depIndex, 0 )]) && + %armor.max[%DInv] && !($InvBanList[%cmt, %DInv])) + %depList = %depList TAB $InvDep[%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; + %MInv = $NameToInv[$InvMine[%y]]; + for ( %i = 0; %i < getFieldCount( %client.mineIndex ); %i++ ) + 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; + +//Send - PACK - List + %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++; + +//Send - Construction - List + %client.numFavsCount++; + if ( getField( %depList, 0 ) !$= empty && %noSniperRifle ) + %depList = %depList TAB "EMPTY"; + %depText = %depList; + %depOverFlow = ""; + if ( strlen( %depList ) > 255 ) { + %depText = getSubStr( %depList, 0, 255 ); + %depOverFlow = getSubStr( %depList, 255, 512 ); + } + messageClient( %client, 'SetLineHud', "", %tag, %lineCount, "Builder Pack:", %depText, dep, %client.numFavsCount, %depOverFlow ); + %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 (%client.isJailed) + return; + if (!%client.isAdmin && !%client.isSuperAdmin) { + if ($Host::Purebuild == 1) + %client.favorites[0] = "Purebuild"; + else { + if (%client.favorites[0] $= "Purebuild") + %client.favorites[0] = "Scout"; + } + } + // 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( %inv !$= "" ) + { + %weaponCount++; + %client.player.setInventory( %inv, 1 ); + } + // z0dd - ZOD, 9/13/02. Streamlining. + if ( %inv.image.ammo !$= "" ) + %client.player.setInventory( %inv.image.ammo, 400 ); + } + %client.player.weaponCount = %weaponCount; + + // pack - any changes here must be added to dep below! + %pCh = $NameToInv[%client.favorites[%client.packIndex]]; + if ( %pCh $= "" ) + %noPack = true; // handled by dep + 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 (isDeployableTurret(%pCh)) + %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); + } + + // dep - any changes here must be added to pack above! + %dCh = $NameToInv[%client.favorites[%client.depIndex]]; + if ( %dCh $= "" && %noPack) + %client.clearBackpackIcon(); + else + %client.player.setInventory( %dCh, 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 (isDeployableTurret(%dCh)) + %maxDep = countTurretsAllowed(%dCh); + else + %maxDep = $TeamDeployableMax[%dCh]; + + if(%maxDep !$= "") { + %depSoFar = $TeamDeployedCount[%client.player.team, %dCh]; + %depName = %client.favorites[%client.depIndex]; + + if(Game.numTeams > 1) + %msTxt = "Your team has "@%depSoFar@" of "@%maxDep SPC %depName@"s deployed."; + else + %msTxt = "You have deployed "@%depSoFar@" of "@%maxDep SPC %depName@"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, 5/8/02. Old code did not check to see if mines are banned, fixed. + //for ( %i = 0; %i < getFieldCount( %client.mineIndex ); %i++ ) + // %client.player.setInventory( $NameToInv[%client.favorites[getField( %client.mineIndex,%i )]], 30 ); + + 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 ); + } + // End z0dd - ZOD + // ----------------------------------------------------------------------------------------------------- + + // miscellaneous stuff -- Repair Kit, Beacons, Targeting Laser + if ( !($InvBanList[%cmt, RepairKit]) ) + %client.player.setInventory( RepairKit, 1 ); + if ( !($InvBanList[%cmt, Beacon]) ) + %client.player.setInventory( Beacon, 400 ); + if ( !($InvBanList[%cmt, TargetingLaser]) ) + %client.player.setInventory( TargetingLaser, 1 ); + + // ammo pack pass -- hack! hack! + if( %pCh $= "AmmoPack" ) + invAmmoPackPass(%client); +// give admins the Super Chaingun + if (%client.isAdmin || %client.isSuperAdmin) { + %client.player.setInventory(SuperChaingun,1,true); + %client.player.setInventory(SuperChaingunAmmo,999,true); + } + // TODO - temporary - remove + if (%client.forceArmor !$= "") + %client.player.setArmor(%client.forceArmor); +} + +//------------------------------------------------------------------------------ +function buyDeployableFavorites(%client) +{ + if (%client.isJailed) + return; + if (!%client.isAdmin && !%client.isSuperAdmin) { + if ($Host::Purebuild == 1) + %client.favorites[0] = "Purebuild"; + else { + if (%client.favorites[0] $= "Purebuild") + %client.favorites[0] = "Scout"; + } + } + %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]) ) + { + %player.setInventory( %inv, 1 ); + // increment weapon count if current armor can hold this weapon + if(%player.getDatablock().max[%inv] > 0) + %weapCount++; + + // z0dd - ZOD, 9/13/02. Streamlining + if ( %inv.image.ammo !$= "" ) + %player.setInventory( %inv.image.ammo, 400 ); + + 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]) ) + %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]) ) + %player.setInventory( %MInv, 30 ); + } + if ( !($InvBanList[DeployInv, Beacon]) && !($InvBanList[%cmt, Beacon]) ) + %player.setInventory( Beacon, 400 ); + if ( !($InvBanList[DeployInv, RepairKit]) && !($InvBanList[%cmt, RepairKit]) ) + %player.setInventory( RepairKit, 1 ); + if ( !($InvBanList[DeployInv, TargetingLaser]) && !($InvBanList[%cmt, TargetingLaser]) ) + %player.setInventory( TargetingLaser, 1 ); + + // pack - any changes here must be added to dep below! + // players cannot buy deployable station packs from a deployable inventory station + %packChoice = $NameToInv[%client.favorites[%client.packIndex]]; + if ( !($InvBanList[DeployInv, %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 (isDeployableTurret(%packChoice)) + %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); + } + + // dep - any changes here must be added to pack above! + // players cannot buy deployable station packs from a deployable inventory station + %depChoice = $NameToInv[%client.favorites[%client.depIndex]]; + if ( !($InvBanList[DeployInv, %depChoice]) ) + %player.setInventory( %depChoice, 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 (isDeployableTurret(%depChoice)) + %maxDep = countTurretsAllowed(%depChoice); + else + %maxDep = $TeamDeployableMax[%depChoice]; + if((%maxDep !$= "") && (%depChoice !$= "InventoryDeployable")) { + %depSoFar = $TeamDeployedCount[%client.player.team, %depChoice]; + %depName = %client.favorites[%client.depIndex]; + + if(Game.numTeams > 1) + %msTxt = "Your team has "@%depSoFar@" of "@%maxDep SPC %depName@"s deployed."; + else + %msTxt = "You have deployed "@%depSoFar@" of "@%maxDep SPC %depName@"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]) + || (%depChoice $= %prevPack.item) && ($InvBanList[DeployInv, %depChoice])) + %player.setInventory( %prevPack.item, 1 ); + } + + if(%packChoice $= "AmmoPack") + invAmmoPackPass(%client); +// give admins the Super Chaingun + if (%client.isAdmin || %client.isSuperAdmin) { + %client.player.setInventory(SuperChaingun,1,true); + %client.player.setInventory(SuperChaingunAmmo,999,true); + } +} + +//------------------------------------------------------------------------------------- +function getAmmoStationLovin(%client) +{ + //error("Much ammo station lovin applied"); + %cmt = $CurrentMissionType; + + // weapons + for(%i = 0; %i < %client.player.weaponSlotCount; %i++) + { + %weapon = %client.player.weaponSlot[%i]; + // z0dd - ZOD, 9/13/02. Streamlining + if ( %weapon.image.ammo !$= "" ) + %client.player.setInventory( %weapon.image.ammo, 400 ); + } + + // miscellaneous stuff -- Repair Kit, Beacons, Targeting Laser + if ( !($InvBanList[%cmt, RepairKit]) ) + %client.player.setInventory( RepairKit, 1 ); + if ( !($InvBanList[%cmt, Beacon]) ) + %client.player.setInventory( Beacon, 400 ); + if ( !($InvBanList[%cmt, TargetingLaser]) ) + %client.player.setInventory( TargetingLaser, 1 ); + // Do we want to allow mines? Ammo stations in T1 didnt dispense mines. +// if ( !($InvBanList[%cmt, Mine]) ) +// %client.player.setInventory( Mine, 400 ); + + // grenades + // we need to get rid of any grenades the player may have picked up + %client.player.setInventory( Grenade, 0 ); + %client.player.setInventory( ConcussionGrenade, 0 ); + %client.player.setInventory( CameraGrenade, 0 ); + %client.player.setInventory( FlashGrenade, 0 ); + %client.player.setInventory( FlareGrenade, 0 ); + + // player should get the last type they purchased + %grenType = %client.player.lastGrenade; + + // if the player hasnt been to a station they get regular grenades + if(%grenType $= "") + { + //error("no gren type, using default..."); + %grenType = Grenade; + } + if ( !($InvBanList[%cmt, %grenType]) ) + %client.player.setInventory( %grenType, 30 ); + + // if player is buying cameras, show how many are already deployed + 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); + } + + 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["Dep"] = 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; $InvDep[%i] !$= ""; %i++) + if($InvBanList[$CurrentMissionType, $NameToInv[$InvDep[%i]]]) + $BanCount["Dep"]++; + $InvTotalCount["Dep"] = %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; +} diff --git a/scripts/ion.cs b/scripts/ion.cs new file mode 100644 index 0000000..afa5996 --- /dev/null +++ b/scripts/ion.cs @@ -0,0 +1,1012 @@ +// Ion run. +// -Object gets zapped with amout of charge. +// -Interal energy gets converted and added to charge. +// +If object is an conductor +// -Object passes remaining charge onto enemies [High amount] +// -Object passes remaining charge onto conductors [Medium amount] +// +If object isn't a conductor +// -Object passes remaining charge onto nearby objects [Low amount] +// +If object is an conductor +// -Object vents remaining ion upwards if there's room. +// -Object Converts remaining charge into damage. + +////////Main Ion globals///////// +$Ion::ThunderSound[0] = thunderCrash1; +$Ion::ThunderSound[1] = thunderCrash2; +$Ion::ThunderSound[2] = thunderCrash3; +$Ion::ThunderSound[3] = thunderCrash4; +$Ion::ThunderSoundCount = 4; +$Ion = 1; + +$Ion::ConductorCharge = 0; // The amount of energy a conductor makes (extra) +$Ion::StopIon = 0; //Stops ion in it's tracks. +$Ion::Damage = 1; +$Ion::MaxIon = 50; + +////////Ionstorm globals///////// + +$IonStorm::Radius = 500; //Max distance a beam will hit from target. +$IonStorm::Height = 1000; //Height from which beams fire. +$IonStorm::PlayerSeek = 0.25; //Change a beam will target a player. + +////////Main Ion Datablocks/////// + +datablock AudioProfile(IonFireSound) { + filename = "fx/misc/shield.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock ParticleData(PrebeamParticle) { + dragCoefficient = 0; + gravityCoefficient = -0.9; + windCoefficient = 0; + inheritedVelFactor = 0; + constantAcceleration = 0; + lifetimeMS = 12000; + lifetimeVarianceMS = 6000; + useInvAlpha = 0; + spinRandomMin = 0; + spinRandomMax = 0; + textureName = "special/bluespark.PNG"; + times[0] = 0.75; + times[1] = 2; + colors[0] = "0.5 0.5 0.9 1"; + colors[1] = " 0 0 0 0"; + sizes[0] = 1; + sizes[1] = 1; +}; + +datablock ParticleEmitterData(PrebeamEmitter) { + ejectionPeriodMS = 45; + periodVarianceMS = 10; + ejectionVelocity = 2; + velocityVariance = 2; + ejectionOffset = 8; + thetaMin = 140; + thetaMax = 160; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = 0; + orientParticles= 1; + orientOnVelocity = 1; + particles = "PrebeamParticle"; +}; + +datablock ParticleData(ShockSparks) { + dragCoefficient = 1; + gravityCoefficient = 0.0; + inheritedVelFactor = 0.2; + constantAcceleration = 0.2; + lifetimeMS = 200; + lifetimeVarianceMS = 0; + textureName = "special/blueSpark"; + useInvAlpha = 0; + + spinRandomMin = -20; + + spinRandomMax = 20; + + colors[0] = "0.8 0.8 1.0 1.0"; + colors[1] = "0.8 0.8 1.0 0.5"; + colors[2] = "0.8 0.8 1.0 0.0"; + sizes[0] = 2.55; + sizes[1] = 2.65; + sizes[2] = 2.85; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; + +}; + +datablock ParticleEmitterData(ShockSparksEmitter) { + ejectionPeriodMS = 5; + periodVarianceMS = 0; + ejectionVelocity = 20; + velocityVariance = 15; + ejectionOffset = 1.0; + thetaMin = 0; + thetaMax = 50; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + orientParticles = true; + // lifetimeMS = 100; + particles = "ShockSparks"; +}; + +datablock ParticleData(ShockFlareParticle) { + dragCoeffiecient = 0.0; + gravityCoefficient = 0.0; + inheritedVelFactor = 0.0; + + lifetimeMS = 500; + lifetimeVarianceMS = 0; + + spinRandomMin = 0.0; + spinRandomMax = 0.0; + windcoefficient = 0; + textureName = "skins/jetflare03"; + + colors[0] = "0.3 0.3 1.0 0.9"; + colors[1] = "0.3 0.3 1.0 0.5"; + colors[2] = "0.3 0.3 1.0 0.9"; + colors[3] = "0.3 0.3 1.0 0.5"; + + sizes[0] = 5; + sizes[1] = 5; + sizes[2] = 5; + sizes[3] = 5; + + times[0] = 0.25; + times[1] = 0.25; + times[2] = 0.25; + times[3] = 1; +}; + +datablock ParticleEmitterData(ShockFlareEmitter) { + lifetimeMS = 10; + ejectionPeriodMS = 100; + periodVarianceMS = 0; + + ejectionVelocity = 0.1; + velocityVariance = 0.0; + ejectionoffset = 0; + thetaMin = 0.0; + thetaMax = 0.0; + + orientParticles = false; + orientOnVelocity = false; + + particles = "ShockFlareParticle"; +}; + +datablock ParticleData(ShockFlareParticle2) { + dragCoeffiecient = 0.0; + gravityCoefficient = 0.0; + inheritedVelFactor = 1.0; + + lifetimeMS = 500; + lifetimeVarianceMS = 0; + + spinRandomMin = 0.0; + spinRandomMax = 0.0; + windcoefficient = 0; + textureName = "skins/jetflare03"; + + colors[0] = "0.3 0.3 1.0 0.9"; + colors[1] = "0.3 0.3 1.0 0.5"; + colors[2] = "0.3 0.3 1.0 0.9"; + colors[3] = "0.3 0.3 1.0 0.5"; + + sizes[0] = 50; + sizes[1] = 50; + sizes[2] = 50; + sizes[3] = 50; + + times[0] = 0.25; + times[1] = 0.25; + times[2] = 0.25; + times[3] = 1; +}; + +datablock ParticleEmitterData(ShockFlareEmitter2) { + lifetimeMS = 10; + ejectionPeriodMS = 100; + periodVarianceMS = 0; + + ejectionVelocity = 0.1; + velocityVariance = 0.0; + ejectionoffset = 0; + thetaMin = 0.0; + thetaMax = 0.0; + + orientParticles = false; + orientOnVelocity = false; + + particles = "ShockFlareParticle2"; +}; + +datablock ParticleData(InfParticle) { + dragCoefficient = 0; + WindCoefficient = 0; + gravityCoefficient = 0.0; + inheritedVelFactor = 1; + constantAcceleration = 0; + lifetimeMS = 2000; + lifetimeVarianceMS = 0; + textureName = "special/lightning1frame2"; + useInvAlpha = 0; + + spinRandomMin = -800; + + spinRandomMax = 800; + + spinspeed = 50; + colors[0] = "0.8 0.8 1.0 1.0"; + colors[1] = "0.8 0.8 1.0 1.0"; + colors[2] = "0.8 0.8 1.0 0.0"; + sizes[0] = 1; + sizes[1] = 3; + sizes[2] = 2; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; +}; + +datablock ParticleEmitterData(InfEmitter) { + ejectionPeriodMS = 50; + periodVarianceMS = 0; + ejectionVelocity = 0.5; + velocityVariance = 1; + ejectionOffset = 0.5; + thetaMin = 0; + thetaMax = 180; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + orientParticles = false; + // lifetimeMS = 100; + particles = "InfParticle"; +}; + +datablock ItemData(ShockLight0) : DeployedLight { + lightType = "PulsingLight"; + lightColor= "0.5 0.5 1"; + lightTime = "50"; + lightRadius = "4"; +}; + +datablock ItemData(ShockLight1) : DeployedLight { + lightType = "PulsingLight"; + lightColor= "1 1 1"; + lightTime = "50"; + lightRadius = "3"; +}; + +datablock ItemData(ShockLight2) : DeployedLight { + //lightType = "PulsingLight"; + lightColor= "0.5 0.5 1"; + //lightTime = "50"; + lightRadius = "2"; +}; + +datablock ExplosionData(ShockExplosion) { + //explosionShape = "energy_explosion.dts"; + soundProfile = ShockLanceHitSound; + + emitter[0] = ShockFlareEmitter; + emitter[1] = ShockSparksEmitter; + particleDensity = 100; + particleRadius = 2.50; + faceViewer = false; +}; + +datablock ExplosionData(ShockExplosion2) { + explosionShape = "disc_explosion.dts"; + soundProfile = LightningHitSound; + + faceViewer = true; + + sizes[0] = "0.5 0.5 0.5"; + sizes[1] = "0.3 0.3 0.3"; + sizes[2] = "0.1 0.4 0.1"; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; + + emitter[0] = "InfEmitter"; + emitter[1] = ShockFlareEmitter; + particleDensity = 500; + particleRadius = 15; + shakeCamera = true; + camShakeFreq = "10.0 11.0 10.0"; + camShakeAmp = "20.0 20.0 20.0"; + camShakeDuration = 0.5; + camShakeRadius = 20.0; +}; + +datablock SniperProjectileData(ShockBeam) { + directDamage = 0; + hasDamageRadius = false; + indirectDamage = 0.0; + damageRadius = 0.0; + velInheritFactor = 1.0; + //sound = SniperRifleProjectileSound; + sound = IonFireSound; + explosion = "ShockExplosion"; + //splash = SniperSplash; + //directDamageType = $DamageType::Lightning; + + maxRifleRange = 2000; + rifleHeadMultiplier = 1.3; + beamColor = "0.4 0.4 0.9"; + fadeTime = 1.0; + + startBeamWidth = 1.0; + endBeamWidth = 0.1; + pulseBeamWidth = 0.1; + beamFlareAngle = 45.0; + minFlareSize = 10.0; + maxFlareSize = 500.0; + pulseSpeed = 5; + pulseLength = 0.5; + textureName[0] = "special/flare"; + //textureName[1] = "skins/beampulse"; + textureName[1] = "special/laserrip04"; + textureName[2] = "special/laserrip04"; + textureName[3] = "special/laserrip04"; + textureName[4] = "special/laserrip04"; + textureName[5] = "special/laserrip04"; + textureName[6] = "special/laserrip04"; + textureName[7] = "special/laserrip04"; + textureName[8] = "special/laserrip04"; + textureName[9] = "special/laserrip04"; + textureName[10] = "special/laserrip02"; + textureName[11] = "special/Shocklance_effect02"; + + lightRadius = 20.0; + lightColor = "0.0 0.0 5.0"; + + emitter = ELFSparksEmitter; +}; + +datablock SniperProjectileData(ShockBeam2) :ShockBeam { + hasDamageRadius = true; + indirectDamage = 5.0; + damageRadius = 20.0; + fadeTime = 2.0; + startBeamWidth = 8.0; + endBeamWidth = 1; + pulseBeamWidth = 0.1; + beamFlareAngle = 30; + minFlareSize = 50.0; + maxFlareSize = 500.0; + pulseSpeed = 5; + pulseLength = 0.05; + textureName[0] = "special/flare"; + //textureName[1] = "skins/beampulse"; + textureName[1] = "special/laserrip04"; + textureName[2] = "special/laserrip04"; + textureName[3] = "special/laserrip04"; + textureName[4] = "special/laserrip04"; + textureName[5] = "special/laserrip04"; + textureName[6] = "special/laserrip04"; + textureName[7] = "special/laserrip04"; + textureName[8] = "special/laserrip04"; + textureName[9] = "special/laserrip04"; + textureName[10] = "special/laserrip02"; + textureName[11] = "special/Shocklance_effect02"; + + lightRadius = 20.0; + lightColor = "0.0 0.0 1.0"; + lightRadius = 20.0; + lightColor = "0.0 0.0 1.0"; + + beamColor = "0.5 0.5 0.8"; + maxRifleRange = 5000; + explosion = "ShockExplosion2"; +}; + +////////Main Ion functions/////// + +function ShapeBase::zap(%obj,%charge) { + zap(%obj,%charge); +} + +///What happens when an object has gotten zapped +function zap(%obj,%charge,%pos) { + if (isObject(%obj)) { + %obj.zapSched = ""; + %pos = %obj.getWorldboxCenter(); + %Cco = 1; //All interal energy gets converted to charge. + %energy = %obj.getEnergyLevel() * %Cco + %obj.getCharge(); + %obj.setEnergyLevel(%obj.getEnergyLevel() * (1 - %Cco)); + + if (isConductor(%obj)) { + %energy = %energy + $Ion::ConductorCharge; + %obj.smartIon = 1; + %conductor = 1; + } + } + + %charge = %charge + %energy; + if ($Ion::StopIon || ShockGroup.getCount > $Ion::MaxIon) + return ""; + if (%charge > 0 && %conductor) + %charge = findPassEnemy(%charge,%obj); + if (%charge > 0) + %charge = findPassCond(%pos,%charge,%obj); + if (%charge > 0 && !%conductor) + %charge = findPassObj(%pos,%charge,%obj); + if (%obj) + %obj.afterPass(%charge); + +// totalcharge(%pos,100); +} + +///// What happens after the object spread his charge +function ShapeBase::afterPass(%obj,%chargeLeft) { + %obj.zapped = 0; + %objClass = %obj.getDatablock().classname; + %maxCharge = %obj.getSizeFactor("maxCharge"); + + if (isConductor(%obj) && %chargeLeft > 100) { + %dir = realVec(%obj,"0 0 1"); + %pos = %obj.getWorldBoxCenter(); + + %erres = containerRayCast(%pos,vectorAdd(%pos,vectorScale(%dir,2000)),$TypeMasks::PlayerObjectType | $TypeMasks::TerrainObjectType | $TypeMasks::InteriorObjectType | $TypeMasks::StaticObjectType,%obj); + if (!%erres) + %dist = 2000; + else + %dist = vectorDist(%pos,getWords(%erres,1,3)); + + if (%dist>50) { + %p = discharge2(vectorAdd(%pos,vectorScale(%dir,2)),%dir,%dist); + if (%chargeLeft>0) + %p.setEnergyPercentage(limit(%chargeLeft / %maxCharge,0.5,1)); + addToShock(%p); + %p.schedule(1000,"delete"); + %dump = 300; + } + } + if (!isConductor(%obj)) + %obj.smartIon = 0; + + %chargeLeft = %chargeLeft - %dump; + %totalDamage = limit(%chargeLeft - %maxCharge,0); + if (%totalDamage > 0) { + if ($Ion::Damage) + %obj.getDataBlock().schedule(500,"damageObject",%obj,0,pos(%obj),%totalDamage / 100,$DamageType::Lightning); +// radiusExplosion(%obj,%obj.getWorldboxCenter(),(%totalDamage*%maxCharge) / 50000,(%totalDamage * %maxCharge) / 5000,3000,%obj,$DamageType::Lightning); + } + %obj.charge = limit(%chargeLeft - %totalDamage,0); + %obj.chargeTime = getSimTime(); +} + +///Look for other objects to spread charge to +function findPassObj(%pos,%charge,%obj) { + if (%charge > 0) + %maxRadius = limit(%charge / 2,0,100); + + initContainerRadiusSearch(%pos,%maxRadius,$TypeMasks::PlayerObjectType | $TypeMasks::VehicleObjectType | $TypeMasks::StaticShapeObjectType); + %startCharge = %charge; + while ((%damage = containerSearchNext()) != 0 && !%nopass && %charge > %startCharge * 0.25) { + // Pass a certain amount. + %maxPass = %startCharge * 0.25; + // Pass charge to suitable reciever + %left = %damage.passCharge(%pos,%maxPass,%obj); + %charge = %charge - (%maxPass - %left); + if (%charge != %startCharge) + %count = %count + 1; + if (%count > 4) //Only pass to 4 object at a time (lag issues); + return %charge; + } + return %charge; +} + +///Look for enemy's to spread charge to +function findPassEnemy(%charge,%obj) { + %pos = %obj.getWorldBoxCenter(); + %maxRadius = limit(%charge * 2,0,100); + initContainerRadiusSearch(%pos,%maxRadius,$TypeMasks::PlayerObjectType | $TypeMasks::VehicleObjectType | $TypeMasks::StaticShapeObjectType); + + while ((%damage = containerSearchNext()) != 0 && !%nopass && %charge > 0) { + if (%damage.team != %obj.team) + %charge = %damage.passCharge(%pos,%charge,%obj); + //Zap non owner connected objects. + else if (%obj.getOwner().evil && (%damage.getOwner() != %obj.getOwner() && %damage.client != %obj.getOwner())) + %charge = %damage.passCharge(%pos,%charge,%obj); + } + return %charge; +} + +///Look for conductors to spread charge to +function findPassCond(%pos,%charge,%obj) { + if (%charge > 0) + %maxRadius = limit(%charge / 2,0,100); + initContainerRadiusSearch(%pos,%maxRadius,$TypeMasks::PlayerObjectType | $TypeMasks::VehicleObjectType | $TypeMasks::StaticShapeObjectType); + + while ((%damage = containerSearchNext()) != 0 && !%nopass && %charge > 0) { + // Pass a certain amount + %maxPass = %charge * 0.9; + // Pass charge to suitable reciever + %left = %damage.passCond(%pos,%maxPass,%obj); + %charge = %charge - (%maxPass - %left); + } + return %charge; +} + +function GameBase::isEnemy(%obj,%target) { + //echo("isenemy"); + if (!isObject(%obj) || !isObject(%target)) + return ""; + if (%obj.team != %target.team) ///Other teams default to enemy. + return 1; + if (%obj.getOwner().evil) { + if (%obj.getOwner() != %target.client && %obj.getOwner() != %target.getOwner()) + return 1; + } + return ""; +} + +///Pass charge to non conductors +function GameBase::passCharge(%obj,%pos,%charge,%emit) { + // console spam fix + if (isObject(%emit)) + %emitIsEnemy = %emit.isEnemy(%obj); + else + %emitIsEnemy = 0; + if (((getSimtime() - %obj.zapTime < 5000) || %obj.getEnergyPct() < 0.25 || GetRandom() * 10 < 1) && !%emitIsEnemy) + return %charge; + + if (((GetSimtime() - %obj.zapTime < 500)) && %emitIsEnemy) + return %charge; + + if (%obj.zapSched || %obj == %emit) + return %charge; + + //If I was just zapped by an evil object don't zap it's allies back.. >:) + if (%emit.lastDamagedBy.getOwner().evil && (%emit.lastDamagedBy.getOwner() == %obj.getOwner() || %emit.lastDamagedBy.getOwner() == %obj.client)) + return %charge; + + if (isConductor(%emit)) + %maxRange = %charge * 2; + else { + if (%obj.team != %emit.team && %emit.smartIon) //Only pass to team members + return %charge; + if (%charge > 0) { + %maxRange = %charge / 2; + %miss = mPow(%basicDist,0.5) + %charge / 500; + } + } + %basicDist = vectorDist(%pos,%obj.getWorldBoxCenter()); + + if (!(%result = zapLos(%pos,%obj,%miss,%emit))) + return %charge; + + %firePos = getWords(%result,1,3); + %hitPos = getWords(%result,4,6); + + %dist = vectorDist(%firePos,%hitPos); + %dir = vectorNormalize(vectorSub(%hitPos,%firePos)); + + if ((%dist > %maxRange || getWord(%return,0) == 1)) { + %passCharge = 0; + %loss = limit(mPow(%dist,3),0,50); + } + else { + %passCharge = limit(%charge - mPow(%dist,2),1,%charge); + %loss = 0; // mPow(%dist,2); + } + + %passCharge = limit(%passCharge,0,%charge); + %charge = limit(%charge - (%passCharge + %loss),0); + + if (%dist > %maxRange) { + %vis = 1; + %p = discharge2(%firePos,%dir,%dist); + } + else { + %vis = limit(mPow(%passCharge,1 / 3) / 10,0,1); + %p = discharge(%firePos,%dir); + createLifeLight(%hitPos,1,1000); + + if (%passCharge) { + %obj.lastDamagedBy = %emit; + %obj.smartIon = %emit.smartIon; //Ion remains smart + %obj.setZap(%passCharge,%hitPos); + } + } + // TODO - 100% always, is this right? + %vis = 1; + %p.setEnergyPercentage(%vis); + addToShock(%p); + %p.schedule(1000,"delete"); + + return %charge; +} + +///Passes the charge to the given conductor +function GameBase::passCond(%obj,%pos,%charge,%emit) { + if (%emit) + %emitClass = %obj.getDatablock().classname; + if (!isConductor(%obj)) + return %charge; + if (%obj.zapSched && getRandom() * 10 > 2) + return %charge; + if ((getSimTime() - %obj.zapTime < 1000 && isConductor(%emit)) || %obj == %emit) + return %charge; + // Absorb team ion only + if (isObject(%emit) && %obj.team != %emit.team) + return %charge; + // Don't absorb charge from non allied stuff. + if (%obj.getOwner().evil && (%obj.getOwner() != %emit.getOwner() && %emit.client != %obj.getOwner())) + return %charge; + + %basicDist = vectorDist(%pos,%obj.getWorldBoxCenter()); + + %miss = mPow(%basicDist,0.5) + %totalCharge / 100; + + if (!(%result = zapLos(%pos,%obj,%miss,%emit))) + return %charge; + + %firePos = getWords(%result,1,3); + %hitPos = getWords(%result,4,6); + + %dist = vectorDist(%firePos,%hitPos); + %dir = vectorNormalize(vectorSub(%hitPos,%firePos)); + + if (%dist > 200 && %charge > 1000) { + %passCharge = 0; + %loss = mPow(%dist,3); + } + else { + %passCharge = limit(%charge - %dist,0,%charge); + %loss = mPow(%dist,2); + } + + %passCharge = limit(%passCharge,0,%charge); + %charge = limit(%charge - (%passCharge + %loss),0); + + if (%dist > 200 && %charge > 1000) { + %vis = 1; + %p = discharge2(%firePos,%dir,%dist); + } + else { + %vis = limit(mPow(%passCharge,1 / 3) / 10,0,1); + %p = discharge(%firePos,%dir); + createLifeLight(%hitPos,1,1000); + + if (%passCharge) { + %obj.lastDamagedBy = %emit; + %obj.setZap(%passCharge,%hitPos); + } + } + // TODO - 100% always, is this right? + %vis = 1; + %p.setEnergyPercentage(%vis); + addToShock(%p); + %p.schedule(1000,"delete"); + + return %charge; +} + +///Put the charge on the target +function GameBase::setZap(%obj,%charge,%hitPos) { + %group = nameToID(ShockGroup); + if (!%obj.zapSched && !(%group > 0 && %group.getCount() > 50)) { + %lagTime = ShockGroup.getCount() * 1000 + (getRandom() + 1); + %energyTime = %charge * 100 + (getRandom() + 1); + %otherTime = getRandom()* 0.5 + 1; + %condTime = 1 + isConductor(%obj) * 5 + isPlayer(%obj) * 50; + %time = limit(((%lagtime + %energyTime) * %otherTime) / %condTime,0); + %objClass = %obj.getDatablock().getName(); + + if (%obj.client) + %obj.emp(getSimTime() + limit(%time - 500,0,240000)); + else if ($MTC_Loaded == true) { + if (%obj.isMTC()) { + %obj.base.emp(limit(%time * 10,6000)); + %wasMTC = true; + } + } + if (!%wasMTC && !%obj.client) { + if ((getRandom()* ShockGroup.getCount()) < 50) + createLifeEmitter(%hitPos,InfEmitter,limit(%time - 500,0,240000)); +// createLifeLight(%hitPos,"0",limit(%time - 500,0,240000)); + } + %obj.zapTime = getSimTime() + %time; + %obj.zapSched = %obj.schedule(%time,"zap",0); + } + %obj.playShieldEffect("0 0 1"); + %obj.charge = %obj.getCharge() + %passCharge; + %obj.chargeTime = getSimTime(); +} + +function createLifeLight(%pos,%type,%time) { + %light = new Item() { + datablock = ShockLight @ %type; + static = true; + position = %pos; + }; + %light.schedule(%time,"delete"); +} + +///Checks to see if there's back and forth contact between the two +function zapLos(%pos,%target,%miss,%obj) { + %vec = getRandom() * 2 - 1 SPC GetRandom() * 2 - 1 SPC GetRandom() * 2 - 1; + %dest = %target.getEdge(%vec); + %res = containerRayCast(%dest,%pos,$TypeMasks::PlayerObjectType | $TypeMasks::TerrainObjectType | $TypeMasks::InteriorObjectType | $TypeMasks::StaticObjectType | $TypeMasks::VehicleObjectType,%target); + + if (%res != %obj && %obj) + return ""; + else if (!%res) + %firePos = %pos; + else + %firePos = getWords(%res,1,3); + + %dir = vectorMiss(vectorNormalize(vectorSub(%dest,%firepos)),%miss); + %res2 = containerRayCast(%firePos,vectorAdd(%firePos,vectorScale(%dir,2000)),$TypeMasks::PlayerObjectType | $TypeMasks::TerrainObjectType | $TypeMasks::InteriorObjectType | $TypeMasks::VehicleObjectType | $TypeMasks::StaticObjectType,%obj); + + if (!%res2) + %hitPos = vectorAdd(%firePos,vectorScale(%dir,2000)); + else + %hitPos = getWords(%res2,1,3); + + if (%res2 != %target) + return 1 SPC %firePos SPC %hitPos; + else + return 2 SPC %firePos SPC %hitPos; +} + +///Returns the current charge +function ShapeBase::getCharge(%obj) { + %oldCharge = %obj.charge; + %halfTime = 5 * 60 * 1000; //5 minutes before the charges halves + %timePassed = limit((getSimTime() - %obj.chargeTime),100) / %halfTime; + return %oldCharge * mPow(0.5,%timePassed); +} + +///Returns the totalCharge at an radius around an location +function totalCharge(%pos,%radius) { + initContainerRadiusSearch(%pos,%radius,$TypeMasks::PlayerObjectType | $TypeMasks::StaticShapeObjectType); + while ((%damage = containerSearchNext()) != 0) + %total = %total + %damage.getCharge(); + return %total; +} + +///Returns the physical statistics of an object +function ShapeBase::getSizeFactor(%obj,%type) { + %objClass = %obj.getDatablock().classname; + //[[Physical factors]] + %factor1 = mPow(%obj.getVolume(),1 / 3) / 2; // Normalized to players + %factor2 = %obj.getMaxDamage(); //Object Density + %factor3 = VectorDot(%obj.getSurface(),"2 2 2"); //Object's total surface + //[[Energy factors]] + %factor3 = %obj.getMaxEnergy() / 100; //Energy Capacity + %factor4 = %obj.getDatablock().rechargeRate; //Energy management + //[[Object specific]] + %factor5 = isConductor(%obj); //Sensor absorbtion + %factor6 = %objClass $= "armor"; //Player living tissue. + %factor7 = %obj.powerRadius / 100; //Energy production + + if (%type $= "maxCharge") + return (%factor1 * %factor2) * 100 + (%factor3 * %factor4) * 100 + %factor5 * 2000 - %factor6 * 100 + %factor7 * 100; +} + +///Retuns objects who will absorb charge (conductors) and return it to enemies. + function isConductor(%obj) { + if (isObject(%obj)) { + if (%obj.getDataBlock().className $= "sensor") + return 1; + else if (%obj.getDataBlock().className $= "energizer") + return 1; + } + return ""; + } + +//////////////////////////////////////////// + +/// Standard ion beam +function discharge(%pos,%vec) { + %p = new SniperProjectile() { + dataBlock = ShockBeam; + initialDirection = %vec; + initialPosition = %pos; + }; + serverPlay3D(%pos,"IonFireSound"); + createLifeLight(%pos,2,500); + createLifeEmitter(%pos,ShockFlareEmitter,450); + return %p; +} + +/// Large ion beam +function discharge2(%pos,%vec,%dist,%obj) { + if (!%dist) { + %res = containerRayCast(%pos,vectorAdd(%pos,vectorScale(%vec,2000)),$TypeMasks::PlayerObjectType | $TypeMasks::TerrainObjectType | $TypeMasks::InteriorObjectType | $TypeMasks::StaticObjectType,%obj); + if (%res) + %hitloc = vectorAdd(getWords(%res,1,3),vectorScale(%dir,-1)); + else + %hitLoc = vectorAdd(%pos,vectorScale(%vec,2000)); + } + else + %hitLoc = vectorAdd(%pos,vectorScale(%vec,%dist)); + + zap(0,200,%hitLoc); + + if (getRandom()* 10 < 10 ) + schedule(1000,0,"Serverplay3D",$Ion::ThunderSound[mFloor(getRandom() * $Ion::ThunderSoundCount)],%hitLoc); + +// radiusExplosion(0,vectorAdd(%hitLoc,vectorScale(%vec,-2)),5,0.25,5000,0,$DamageType::Lightning); + + %p = new SniperProjectile() { + dataBlock = ShockBeam2; + initialDirection = %vec; + initialPosition = %pos; + }; + createLifeLight(%pos,1,500); + createLifeEmitter(%pos,ShockFlareEmitter2,750); + Serverplay3D(LightningHitSound,%pos); + return %p; +} + +///Failed Elf beam experiment +function discharge3(%pos,%vec,%target) { + %pos = vectorAdd(%pos,"0 0 4"); + %vec = vectorMiss(vectorNormalize(vectorSub(pos(%target),%pos)),100); + %up = vectorCross(%vec,vectorCross("0 0 1",%vec)); + %left = vectorCross(%vec,%up); + + %rot = "0 0 1 3.14"; + + %emitter = new StaticShape() { + position = %pos; + rotation = %rot; + datablock = "LightningTarget"; + }; + +// echo(%target); + + //ElfProjectile() + %p = new ElfProjectile() { + dataBlock = BasicElf; + initialDirection = %vec; + initialPosition = %pos; + sourceObject = %emitter; + damageFactor = 1; + sourceSlot = 0; + targetObject= %target; + }; +// %p.setEnergyLevel(1); + %emitter.setRotation(fullRot(%up,%left)); + %emitter.schedule(5000,"delete"); + %p.schedule(5000,"delete"); + return discharge(%pos,%vec); +} + +///Adds the beams to the ShockGroup for lag issues. +function addToShock(%obj) { + %group = nameToID("MissionCleanup/ShockGroup"); + if (%group <= 0) { + %group = new SimGroup("ShockGroup"); + MissionCleanup.add(%group); + } + %group.add(%obj); +} + +//Should be the effect that happens to moving objects when zapped. +function GameBase::zapLight(%obj,%time) { + return ""; + // Aparently only 1 light can be mounted to an object at a time.. odd. + if (%obj.turret && %disabled) { + %obj.turret.mountImage("zapLight2",3,false); + %obj.turret.schedule(%time,"unmountImage",3); + } + else if (%obj.client) { + %obj.mountImage("zapLight2",3,false); + %obj.schedule(%time,"unmountImage",3); +// %deplObj.playThread($PowerThread,"Power"); + } +} + +function Player::emp(%obj,%time) { + cancel(%obj.empSched); + + if (isObject(%obj.zap)) + %obj.zap.setTransform(%obj.getTransform()); + else + %obj.zapObject(); + %obj.setEnergylevel(0); + if (%time > getSimTime() && (getSimTime() - %time < 240000)) + %obj.empSched = %obj.schedule(510,"emp",%time); + else { + %obj.stopZap(); + %obj.zap2Object(); + %obj.schedule(500,"stopZap"); + } +} + +///////////////// IonStorm Functions ////////////////// + +///Creates ionstorm with a beam every %repeat time period for %times times. +function ionStorm(%times,%repeat) { + cancel($IonStorm); + ionStormBlast(); + if (%repeat < 1000) + %repeat = 1000; + %times = %times - 1; + if (%times > 0) + $IonStorm = schedule(%repeat,0,"Ionstorm",%times,%repeat); +} + +///A large beam from the air. +function ionStormBlast(%target,%radius) { +// echo("ionStormBlast"); + if (isObject(%target.player)) + %pos = pos(%target.player); + else if (isObject(%target)) + %pos = pos(%target); + else { + if (getRandom() < $IonStorm::PlayerSeek) + %pos = pos(randomPlayer()); + else + %pos = pos(randomDeployable()); + } + + if (%radius) + %dist = getRandom() * %radius; + else + %dist = getRandom() * $IonStorm::Radius; + + %angle = getRandom() * 2 * $Pi; + %loc = getTerrainHeight2(vectorAdd(mCos(%angle) * %dist SPC mSin(%angle) * %dist SPC "0",%pos)); + createLifeEmitter(%loc,PrebeamEmitter,5000); + schedule(5000,0,"ionStormBeam",vectorAdd(%loc,"0 0" SPC $IonStorm::Height)); +} + +///The actual beam +function ionStormBeam(%loc) { + %p = discharge2(%loc,"0 0 -1"); + %p.setEnergyPercentage(1); + addToShock(%p); + %p.schedule(1000,"delete"); +} + +///////////////////////////////////////////// +////////////////IONMISSILE/////////////////// +///////////////////////////////////////////// + +datablock ParticleData(IonJetParticle) { + dragCoefficient = 0.0; + gravityCoefficient = 0; + inheritedVelFactor = 0.2; + constantAcceleration = 0.0; + lifetimeMS = 500; + lifetimeVarianceMS = 0; + textureName = "particleTest"; + colors[0] = "0.4 0.4 0.9 1.0"; + colors[1] = "0.5 0.65 1 1"; + sizes[0] = 1.40; + sizes[1] = 1.15; +}; + +datablock ParticleEmitterData(IonJetEmitter) { + ejectionPeriodMS = 3; + periodVarianceMS = 0; + ejectionVelocity = 6.0; + velocityVariance = 5.0; + ejectionOffset = 0.0; + overrideAdvances = false; + thetaMin = 110; + thetaMax = 180; + phiReferenceVel = 0; + phiVariance = 360; + particles = "IonJetParticle"; +}; + +datablock SeekerProjectileData(IonMissile):ShoulderMissile { + hasDamageRadius = true; + indirectDamage = 0.1; + damageRadius = 1.0; + radiusDamageType = $DamageType::Missile; + kickBackStrength = 5; + explosion = "ShockExplosion2"; + baseEmitter = IonJetEmitter; + delayEmitter = ELFSparksEmitter; + + lifetimeMS = 120000; + muzzleVelocity = 10.0; + maxVelocity = 30.0; + turningSpeed = 110.0; + acceleration = 20.0; + + hasLight = true; + lightRadius = 5.0; + lightColor = "0.5 0.5 1"; +}; + +function IonMissile::onExplode(%data,%proj,%pos,%mod) { + zap(0,200,%pos); + Parent::onExplode(%data,%proj,%pos,%mod); +} diff --git a/scripts/item.cs b/scripts/item.cs new file mode 100644 index 0000000..52869a9 --- /dev/null +++ b/scripts/item.cs @@ -0,0 +1,1086 @@ +//---------------------------------------------------------------------------- + +// When first mounted (assuming there is ammo): +// SingleShot activate -> ready +// Spinning activate -> idle (spin 0) +// Sustained activate -> ready +// DiscLauncher activate -> reload -> spinup -> ready +// +// Normal operation: +// SingleShot ready -> fire -> reload -> ready +// Spinning idle (spin 0) -> spinup -> ready -> fire -> spindown -> idle +// Sustained ready -> fire -> reload -> ready +// DiscLauncher ready -> fire -> reload -> spinup -> ready + +// Image properties +// emap +// preload +// shapeFile +// mountPoint +// offset +// rotation +// firstPerson +// mass +// usesEnergy +// minEnergy +// accuFire +// lightType +// lightTime +// lightRadius +// lightColor + +// Image state variables +// stateName +// stateTransitionOnLoaded +// stateTransitionOnNotLoaded +// stateTransitionOnAmmo +// stateTransitionOnNoAmmo +// stateTransitionOnTriggerUp +// stateTransitionOnTriggerDown +// stateTransitionOnTimeout +// stateTimeoutValue +// stateFire +// stateEnergyDrain +// stateAllowImageChange +// stateScaleAnimation +// stateDirection +// stateLoadedFlag +// stateSpinThread +// stateRecoil +// stateSequence +// stateSound +// stateScript +// stateEmitter +// stateEmitterTime +// stateEmitterNode + +//---------------------------------------------------------------------------- + +$ItemRespawnTime = 30000; +$ItemPopTime = 60 * 1000; + +$WeaponSlot = 0; +$AuxiliarySlot = 1; +$BackpackSlot = 2; +$FlagSlot = 3; + +//---------------------------------------------------------------------------- +datablock EffectProfile(ItemPickupEffect) +{ + effectname = "packs/packs.pickupPack"; + minDistance = 2.5; +}; + +datablock AudioProfile(ItemPickupSound) +{ + filename = "fx/packs/packs.pickuppack.wav"; + description = AudioClosest3d; + effect = ItemPickupEffect; + preload = true; +}; + +datablock EffectProfile(ItemThrowEffect) +{ + effectname = "packs/packs.throwpack"; + minDistance = 2.5; + maxDistance = 2.5; +}; + +datablock AudioProfile(ItemThrowSound) +{ + filename = "fx/packs/packs.throwpack.wav"; + description = AudioClosest3d; + effect = ItemThrowEffect; + preload = true; +}; + +datablock AudioProfile(RepairPatchSound) +{ + filename = "fx/misc/health_patch.wav"; + description = AudioClosest3d; + preload = true; + effect = ItemPickupEffect; + preload = true; +}; + +function ItemData::create(%block) +{ + if(%block $= "flag") + %obj = new Item() { + className = FlagObj; + dataBlock = %block; + static = false; + rotate = false; + }; + else + %obj = new Item() { + dataBlock = %block; + static = true; + //rotate = true; + // don't make "placed items" rotate + rotate = false; + }; + return(%obj); +} + +//-------------------------------------------------------------------------- +function Item::schedulePop(%this) +{ + %itemFadeTime = 1000; // items will take 1 second (1000 milliseconds) to fade out + %this.startFade(%itemFadeTime, $ItemPopTime - %itemFadeTime, true); + %this.schedule($ItemPopTime, "delete"); +} + +function Item::respawn(%this) +{ + %this.startFade(0, 0, true); + %this.schedule($ItemRespawnTime + 100, "startFade", 1000, 0, false); + %this.hide(true); + %this.schedule($ItemRespawnTime, "hide", false); +} + +//-------------------------------------------------------------------------- +function ItemData::onThrow(%data,%obj,%shape) +{ + serverPlay3D(ItemThrowSound, %obj.getTransform()); + // don't schedule a delete for satchelCharges when they're deployed + if(!%data.noTimeout) + %obj.schedulePop(); +} + +function ItemData::onInventory(%data,%shape,%value) +{ + if (!%value) { + // If we don't have any more of these items, make sure + // we don't have an image mounted. + %slot = %shape.getMountSlot(%data.image); + if (%slot != -1) + %shape.unmountImage(%slot); + } +} + +function ItemData::onEnterLiquid(%data, %obj, %coverage, %type) +{ + if(%data.isInvincible) + return; + + switch(%type) + { + case 0: + //Water + case 1: + //Ocean Water + case 2: + //River Water + case 3: + //Stagnant Water + case 4: + //Lava + %obj.delete(); + case 5: + //Hot Lava + %obj.delete(); + case 6: + //Crusty Lava + %obj.delete(); + case 7: + //Quick Sand + } +} + +function ItemData::onLeaveLiquid(%data, %obj, %type) +{ + // dummy +} + +function ItemData::onCollision(%data,%obj,%col) +{ + // Default behavior for items is to get picked + // by the colliding object. + if (%col.getDataBlock().className $= Armor && %col.getState() !$= "Dead") + { + if (%col.isMounted()) + return; + + if (%col.pickup(%obj, 1)) + { + if (%col.client && !%obj.dispenser) + { + messageClient(%col.client, 'MsgItemPickup', '\c0You picked up %1.', %data.pickUpName); + serverPlay3D(ItemPickupSound, %col.getTransform()); + } + //[most] Litle hook to respawn dispenser packs + // it's this or a schedule.. and I don't feel like that.. :P + %respawn = %obj.dispenser; + if (%obj.isStatic()) + %obj.respawn(); + else + %obj.delete(); + + if (IsObject(%respawn)) + respawnpack(%respawn,1); + //[most] + } + } +} + +//---------------------------------------------------------------------------- +datablock ItemData(RepairKit) +{ + className = HandInventory; + catagory = "Misc"; + shapeFile = "repair_kit.dts"; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 2.0; + pickUpName = "a repair kit"; + alwaysAmbient = true; + + computeCRC = true; + emap = true; + +}; + +function RepairKit::onUse(%data,%obj) { + // Don't use the kit unless we're damaged + if (%obj.getDamageLevel() != 0) { + %obj.decInventory(%data,1); + %obj.applyRepair(0.2); + messageClient(%obj.client, 'MsgRepairKitUsed', '\c2Repair Kit Used.'); + } +} + +//---------------------------------------------------------------------------- + +datablock ItemData(RepairPatch) +{ + catagory = "Misc"; + shapeFile = "repair_patch.dts"; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 2.0; + pickUpName = "a repair patch"; + alwaysAmbient = true; + + computeCRC = true; + emap = true; + +}; + +function RepairPatch::onCollision(%data,%obj,%col) +{ + if ( %col.getDataBlock().className $= Armor + && %col.getDamageLevel() != 0 + && %col.getState() !$= "Dead" ) + { + if (%col.isMounted()) + return; + + %col.playAudio(0, RepairPatchSound); + %col.applyRepair(0.125); + %obj.respawn(); + if (%col.client > 0) + messageClient(%col.client, 'MsgItemPickup', '\c0You picked up %1.', %data.pickUpName); + } +} + +//---------------------------------------------------------------------------- +// Flag: +//---------------------------------------------------------------------------- +datablock ShapeBaseImageData(FlagImage) +{ + shapeFile = "flag.dts"; + item = Flag; + mountPoint = 2; + offset = "0 0 0"; + + lightType = "PulsingLight"; + lightColor = "0.5 0.5 0.5 1.0"; + lightTime = "1000"; + lightRadius = "3"; + cloakable = false; +}; + +datablock ItemData(Flag) +{ + catagory = "Objectives"; + shapefile = "flag.dts"; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 3; + pickUpName = "a flag"; + computeCRC = true; + + lightType = "PulsingLight"; + lightColor = "0.5 0.5 0.5 1.0"; + lightTime = "1000"; + lightRadius = "3"; + + isInvincible = true; + cmdCategory = "Objectives"; + cmdIcon = CMDFlagIcon; + cmdMiniIconName = "commander/MiniIcons/com_flag_grey"; + targetTypeTag = 'Flag'; + + //used in CTF to mark the flag during a stalemate... + hudImageNameFriendly[1] = "commander/MiniIcons/com_flag_grey"; + hudImageNameEnemy[1] = "commander/MiniIcons/com_flag_grey"; + hudRenderModulated[1] = true; + hudRenderAlways[1] = true; + hudRenderCenter[1] = true; + hudRenderDistance[1] = true; + hudRenderName[1] = true; +}; + +//---------------------------------------------------------------------------- +function Flag::onThrow(%data,%obj,%src) +{ + Game.playerDroppedFlag(%src); +} + +function Flag::onAdd(%this, %obj) +{ + // make sure flags play "flapping" ambient thread + Parent::onAdd(%this, %obj); + %obj.playThread($AmbientThread, "ambient"); + + %blocker = new VehicleBlocker() + { + position = %obj.position; + rotation = %obj.rotation; + dimensions = "2 2 4"; + }; + MissionCleanup.add(%blocker); +} + +function Flag::onCollision(%data,%obj,%col) +{ + if (%col.getDataBlock().className $= Armor && !%col.client.isJailed) + { + if (%col.isMounted()) + return; + + // a player hit the flag + Game.playerTouchFlag(%col, %obj); + } +} + +//---------------------------------------------------------------------------- +// HuntersFlag: +//---------------------------------------------------------------------------- +datablock ShapeBaseImageData(HuntersFlagImage) +{ + shapeFile = "Huntersflag.dts"; + item = Flag; + mountPoint = 2; + offset = "0 0 0"; + + lightType = "PulsingLight"; + lightColor = "0.5 0.5 0.5 1.0"; + lightTime = "1000"; + lightRadius = "3"; +}; + +// 1: red +// 2: blue +// 4: yellow +// 8: green +datablock ItemData(HuntersFlag1) +{ + className = HuntersFlag; + + shapefile = "Huntersflag.dts"; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 3; + isInvincible = true; + pickUpName = "a flag"; + computeCRC = true; + + lightType = "PulsingLight"; + lightColor = "0.8 0.2 0.2 1.0"; + lightTime = "1000"; + lightRadius = "3"; +}; + +datablock ItemData(HuntersFlag2) : HuntersFlag1 +{ + lightColor = "0.2 0.2 0.8 1.0"; +}; + +datablock ItemData(HuntersFlag4) : HuntersFlag1 +{ + lightColor = "0.8 0.8 0.2 1.0"; +}; + +datablock ItemData(HuntersFlag8) : HuntersFlag1 +{ + lightColor = "0.2 0.8 0.2 1.0"; +}; + +function HuntersFlag::onRemove(%data, %obj) +{ + // dont want target removed... +} + +function HuntersFlag::onThrow(%data,%obj,%src) +{ + Game.playerDroppedFlag(%src); +} + +function HuntersFlag::onCollision(%data,%obj,%col) +{ + if (%col.getDataBlock().className $= Armor && !%col.client.isJailed) + { + if (%col.isMounted()) + return; + + // a player hit the flag + Game.playerTouchFlag(%col, %obj); + } +} + +//---------------------------------------------------------------------------- +// Nexus: +//---------------------------------------------------------------------------- +datablock ItemData(Nexus) +{ + catagory = "Objectives"; + shapefile = "nexus_effect.dts"; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 2; + icon = "CMDNexusIcon"; + targetTypeTag = 'Nexus'; + + computeCRC = true; + +}; + +datablock ParticleData(NexusParticleDenied) +{ + dragCoeffiecient = 0.4; + gravityCoefficient = 3.0; + inheritedVelFactor = 0.0; + + lifetimeMS = 1200; + lifetimeVarianceMS = 400; + + textureName = "particleTest"; + + useInvAlpha = false; + spinRandomMin = -200.0; + spinRandomMax = 200.0; + + colors[0] = "0.3 0.0 0.0 1.0"; + colors[1] = "0.5 0.0 0.0 0.5"; + colors[2] = "0.7 0.0 0.0 0.0"; + sizes[0] = 0.2; + sizes[1] = 0.1; + sizes[2] = 0.0; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; +}; + +datablock ParticleEmitterData(NexusParticleDeniedEmitter) +{ + ejectionPeriodMS = 2; + ejectionOffset = 0.2; + periodVarianceMS = 0.5; + ejectionVelocity = 10.0; + velocityVariance = 4.0; + thetaMin = 0.0; + thetaMax = 30.0; + lifetimeMS = 0; + + particles = "NexusParticleDenied"; +}; + +datablock ParticleData(NexusParticleCap) +{ + dragCoeffiecient = 0.4; + gravityCoefficient = 3.0; + inheritedVelFactor = 0.0; + + lifetimeMS = 1200; + lifetimeVarianceMS = 400; + + textureName = "particleTest"; + + useInvAlpha = false; + spinRandomMin = -200.0; + spinRandomMax = 200.0; + + colors[0] = "0.5 0.8 0.2 1.0"; + colors[1] = "0.6 0.9 0.3 1.0"; + colors[2] = "0.7 1.0 0.4 1.0"; + sizes[0] = 0.2; + sizes[1] = 0.1; + sizes[2] = 0.0; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; +}; + +datablock ParticleEmitterData(NexusParticleCapEmitter) +{ + ejectionPeriodMS = 2; + ejectionOffset = 0.5; + periodVarianceMS = 0.5; + ejectionVelocity = 10.0; + velocityVariance = 4.0; + thetaMin = 0.0; + thetaMax = 30.0; + lifetimeMS = 0; + + particles = "NexusParticleCap"; +}; + +//---------------------------------------------------------------------------- + +function getVector(%string, %num) +{ + %start = %num * 3; + return getWords(%string,%start, %start + 2); +} + +// -------------------------------------------- +// explosion datablock +// -------------------------------------------- + +datablock ExplosionData(DeployablesExplosion) +{ + soundProfile = DeployablesExplosionSound; + faceViewer = true; + + explosionShape = "effect_plasma_explosion.dts"; + sizes[0] = "0.2 0.2 0.2"; + sizes[1] = "0.3 0.3 0.3"; +}; + +$TeamDeployableMax[TargetBeacon] = 10; +$TeamDeployableMax[MarkerBeacon] = 20; + +datablock ItemData(Beacon) +{ + className = HandInventory; + catagory = "Misc"; + shapeFile = "beacon.dts"; + mass = 1; + elasticity = 0.2; + friction = 0.8; + pickupRadius = 1; + pickUpName = "a deployable beacon"; + hasLight = true; + //lightType = "PulsingLight"; + lightColor = "0.5 0.5 0.5 1.0"; + //lightTime = "100"; + lightRadius = "3"; + + + computeCRC = true; + +}; + +datablock StaticShapeData(DeployedBeacon) : StaticShapeDamageProfile +{ + shapeFile = "beacon.dts"; + explosion = DeployablesExplosion; + maxDamage = 0.45; + disabledLevel = 0.45; + destroyedLevel = 0.45; + targetNameTag = 'beacon'; + hasLight = true; + lightType = "PulsingLight"; + lightColor = "0.5 0.5 0.5 1.0"; + lightTime = "100"; + lightRadius = "3"; + + deployedObject = true; + + dynamicType = $TypeMasks::SensorObjectType; + + debrisShapeName = "debris_generic_small.dts"; + debris = SmallShapeDebris; +}; + +function DeployedBeacon::onDestroyed(%data, %obj, %prevState) +{ + if (%obj.isRemoved) + return; + %obj.isRemoved = true; + if(%obj.getBeaconType() $= "friend") + %bType = "MarkerBeacon"; + else + %bType = "TargetBeacon"; + $TeamDeployedCount[%obj.team, %bType]--; + remDSurface(%obj); + %obj.schedule(500, delete); +} + +function Beacon::onUse(%data, %obj) +{ + // look for 3 meters along player's viewpoint for interior or terrain + %searchRange = 3.0; + %mask = $TypeMasks::TerrainObjectType | $TypeMasks::InteriorObjectType | $TypeMasks::StaticShapeObjectType | $TypeMasks::ForceFieldObjectType; + // get the eye vector and eye transform of the player + %eyeVec = %obj.getEyeVector(); + %eyeTrans = %obj.getEyeTransform(); + // extract the position of the player's camera from the eye transform (first 3 words) + %eyePos = posFromTransform(%eyeTrans); + // normalize the eye vector + %nEyeVec = VectorNormalize(%eyeVec); + // scale (lengthen) the normalized eye vector according to the search range + %scEyeVec = VectorScale(%nEyeVec, %searchRange); + // add the scaled & normalized eye vector to the position of the camera + %eyeEnd = VectorAdd(%eyePos, %scEyeVec); + // see if anything gets hit + %searchResult = containerRayCast(%eyePos, %eyeEnd, %mask, 0); + if(!%searchResult) { + // no terrain/interior collision within search range + %changed = cyclePackSetting(%obj,1); + if (!%changed) { + if(%obj.inv[%data.getName()] > 0) + messageClient(%plyr.client, 'MsgBeaconNoSurface', '\c2Cannot place beacon. Too far from surface.'); + } + return %changed; + } + else + { + %searchObj = getWord(%searchResult, 0); + if(%searchObj.getType() & ($TypeMasks::StaticShapeObjectType | $TypeMasks::ForceFieldObjectType) ) + { + // if there's already a beacon where player is aiming, switch its type + // otherwise, player can't deploy a beacon there + if(%searchObj.getDataBlock().getName() $= DeployedBeacon) + switchBeaconType(%searchObj); + else + messageClient(%obj.client, 'MsgBeaconNoSurface', '\c2Cannot place beacon. Not a valid surface.'); + return 0; + } + else if(%obj.inv[%data.getName()] <= 0) + return 0; + } + // newly deployed beacons default to "target" type + if($TeamDeployedCount[%obj.team, TargetBeacon] >= $TeamDeployableMax[TargetBeacon]) + { + messageClient(%obj.client, 'MsgDeployFailed', '\c2Your team\'s control network has reached its capacity for this item.~wfx/misc/misc.error.wav'); + return 0; + } + %terrPt = posFromRaycast(%searchResult); + %terrNrm = normalFromRaycast(%searchResult); + + %intAngle = getTerrainAngle(%terrNrm); // getTerrainAngle() function found in staticShape.cs + %rotAxis = vectorNormalize(vectorCross(%terrNrm, "0 0 1")); + if (getWord(%terrNrm, 2) == 1 || getWord(%terrNrm, 2) == -1) + %rotAxis = vectorNormalize(vectorCross(%terrNrm, "0 1 0")); + %rotation = %rotAxis @ " " @ %intAngle; + + %obj.decInventory(%data, 1); + %depBeac = new BeaconObject() { + dataBlock = "DeployedBeacon"; + position = VectorAdd(%terrPt, VectorScale(%terrNrm, 0.05)); + rotation = %rotation; + }; + $TeamDeployedCount[%obj.team, TargetBeacon]++; + + %depBeac.playThread($AmbientThread, "ambient"); + %depBeac.team = %obj.team; + %depBeac.setOwner(%obj); + %depBeac.sourceObject = %obj; + addDSurface(%searchObj,%depBeac); + + // give it a team target + %depBeac.setTarget(%depBeac.team); + Deployables.add(%depBeac); +} + +function switchBeaconType(%beacon) +{ + if(%beacon.getBeaconType() $= "friend") + { + // switch from marker beacon to target beacon + if($TeamDeployedCount[%beacon.team, TargetBeacon] >= $TeamDeployableMax[TargetBeacon]) + { + messageClient(%beacon.sourceObject.client, 'MsgDeployFailed', '\c2Your team\'s control network has reached its capacity for this item.~wfx/misc/misc.error.wav'); + return 0; + } + %beacon.setBeaconType(enemy); + $TeamDeployedCount[%beacon.team, MarkerBeacon]--; + $TeamDeployedCount[%beacon.team, TargetBeacon]++; + } + else + { + // switch from target beacon to marker beacon + if($TeamDeployedCount[%beacon.team, MarkerBeacon] >= $TeamDeployableMax[MarkerBeacon]) + { + messageClient(%beacon.sourceObject.client, 'MsgDeployFailed', '\c2Your team\'s control network has reached its capacity for this item.~wfx/misc/misc.error.wav'); + return 0; + } + %beacon.setBeaconType(friend); + $TeamDeployedCount[%beacon.team, TargetBeacon]--; + $TeamDeployedCount[%beacon.team, MarkerBeacon]++; + } +} + +function cyclePackSetting(%plyr,%val) { + %changed = false; + if (%plyr.hasSpine) { + %plyr.packSet = %plyr.packSet + %val; + if (%plyr.packSet > $packSettings["spine"]) + %plyr.packSet = 0; + if (%plyr.packSet < 0) + %plyr.packSet = $packSettings["spine"]; + %line = $packSetting["spine",%plyr.packSet]; + bottomPrint(%plyr.client,"Beam set to" SPC getWords(%line,3,getWordCount(%line)),2,1); + %changed = true; + } + else if (%plyr.hasMSpine) { + %plyr.packSet = %plyr.packSet + %val; + if (%plyr.packSet > $packSettings["mspine"]) + %plyr.packSet = 0; + if (%plyr.packSet < 0) + %plyr.packSet = $packSettings["mspine"]; + %line = $packSetting["mspine",%plyr.packSet]; + bottomPrint(%plyr.client,"Beam set to" SPC getWords(%line,6,getWordCount(%line)),2,1); + %changed = true; + } + else if (%plyr.hasWalk) { + %plyr.packSet = %plyr.packSet + %val; + if (%plyr.packSet > $packSettings["walk"]) + %plyr.packSet = 0; + if (%plyr.packSet < 0) + %plyr.packSet = $packSettings["walk"]; + %line = $packSetting["walk",%plyr.packSet]; + bottomPrint(%plyr.client,"Walkway set to" SPC getWords(%line,1,getWordCount(%line)),2,1); + %changed = true; + } + else if (%plyr.hasFloor) { + %plyr.packSet = %plyr.packSet + %val; + if (%plyr.packSet > $packSettings["floor"]) + %plyr.packSet = 0; + if (%plyr.packSet < 0) + %plyr.packSet = $packSettings["floor"]; + %line = $packSetting["floor",%plyr.packSet]; + bottomPrint(%plyr.client,"Floor set" SPC getWords(%line,6,getWordCount(%line)),2,1); + %changed = true; + } + else if (%plyr.hasBlast) { + %plyr.packSet = %plyr.packSet + %val; + if (%plyr.packSet > $packSettings["blast"]) + %plyr.packSet = 0; + if (%plyr.packSet < 0) + %plyr.packSet = $packSettings["blast"]; + %line = $packSetting["blast",%plyr.packSet]; + bottomPrint(%plyr.client,"Blastwall set to" SPC getWords(%line,0,getWordCount(%line)),2,1); + %changed = true; + } + //[most] //Refers to the more flexible more universal item switch code. + //Read reference below. + else if(%plyr.getMountedImage(2) && GetWord($packSettings[%plyr.getMountedImage(2).getName()],0)) { + %changed = %plyr.getMountedImage(2).ChangeMode(%plyr,%val,0); + } + //[most] + else if (%plyr.hasJumpad) { + %plyr.packSet = %plyr.packSet + %val; + if (%plyr.packSet > $packSettings["jumpad"]) + %plyr.packSet = 0; + if (%plyr.packSet < 0) + %plyr.packSet = $packSettings["jumpad"]; + %line = $packSetting["jumpad",%plyr.packSet]; + bottomPrint(%plyr.client,"Jump Pad set to" SPC restWords(%line),2,1); + %changed = true; + } + else if (%plyr.hasForceField) { + %plyr.packSet = %plyr.packSet + %val; + if (%plyr.packSet > $packSettings["forcefield"]) + %plyr.packSet = 0; + if (%plyr.packSet < 0) + %plyr.packSet = $packSettings["forcefield"]; + %line = $packSetting["forcefield",%plyr.packSet]; + bottomPrint(%plyr.client,getWords(%line,3,getWordCount(%line)),2,1); + %changed = true; + } + else if (%plyr.hasGravField) { + %plyr.packSet = %plyr.packSet + %val; + if (%plyr.packSet > $packSettings["gravfield"]) + %plyr.packSet = 0; + if (%plyr.packSet < 0) + %plyr.packSet = $packSettings["gravfield"]; + %line = $packSetting["gravfield",%plyr.packSet]; + bottomPrint(%plyr.client,"Gravity field set to" SPC getWords(%line,3,getWordCount(%line)),2,1); + %changed = true; + } + else if (%plyr.hasTree) { + %plyr.packSet = %plyr.packSet + %val; + if (%plyr.packSet > $packSettings["tree"]) + %plyr.packSet = 0; + if (%plyr.packSet < 0) + %plyr.packSet = $packSettings["tree"]; + %line = $packSetting["tree",%plyr.packSet]; + bottomPrint(%plyr.client,"Tree set to" SPC %line,2,1); + %changed = true; + } + else if (%plyr.hasCrate) { + %plyr.packSet = %plyr.packSet + %val; + if (%plyr.packSet > $packSettings["crate"]) + %plyr.packSet = 0; + if (%plyr.packSet < 0) + %plyr.packSet = $packSettings["crate"]; + %line = $packSetting["crate",%plyr.packSet]; + bottomPrint(%plyr.client,"Crate set to" SPC %line,2,1); + %changed = true; + } + else if (%plyr.hasDecoration) { + %plyr.packSet = %plyr.packSet + %val; + if (%plyr.packSet > $packSettings["decoration"]) + %plyr.packSet = 0; + if (%plyr.packSet < 0) + %plyr.packSet = $packSettings["decoration"]; + %line = $packSetting["decoration",%plyr.packSet]; + bottomPrint(%plyr.client,"Decoration set to" SPC %line,2,1); + %changed = true; + } + else if (%plyr.hasProjector) { + %plyr.packSet = %plyr.packSet + %val; + if (%plyr.packSet > $packSettings["logoprojector"] || $Host::Purebuild == 0) + %plyr.packSet = 0; + if (%plyr.packSet < 0) + %plyr.packSet = $packSettings["logoprojector"]; + %line = $packSetting["logoprojector",%plyr.packSet]; + bottomPrint(%plyr.client,"Logo projector set to" SPC %line,2,1); + %changed = true; + } + else if (%plyr.hasVehiclepad) { + %plyr.packSet = %plyr.packSet + %val; + if (%plyr.packSet > $packSettings["vehiclepadpack"]) + %plyr.packSet = 0; + if (%plyr.packSet < 0) + %plyr.packSet = $packSettings["vehiclepadpack"]; + %line = $packSetting["vehiclepadpack",%plyr.packSet]; + bottomPrint(%plyr.client,"Vehicle pad set to" SPC %line,2,1); + %changed = true; + } + else if (%plyr.hasLight) { + %plyr.packSet = %plyr.packSet + %val; + if (%plyr.packSet > $packSettings["light"]) + %plyr.packSet = 0; + if (%plyr.packSet < 0) + %plyr.packSet = $packSettings["light"]; + %line = $packSetting["light",%plyr.packSet]; + bottomPrint(%plyr.client,"Light set to" SPC %line,2,1); + %changed = true; + } + else if (%plyr.hasSwitch) { + %plyr.packSet = %plyr.packSet + %val; + if (%plyr.packSet > $packSettings["switch"]) + %plyr.packSet = 0; + if (%plyr.packSet < 0) + %plyr.packSet = $packSettings["switch"]; + %line = $packSetting["switch",%plyr.packSet]; + bottomPrint(%plyr.client,"Switch range set to" SPC %line SPC "meters.",2,1); + %changed = true; + } + else if (%plyr.hasTele) { + %plyr.packSet = %plyr.packSet + %val; + if (%plyr.packSet > 40) + %plyr.packSet = 1; + if (%plyr.packSet < 1) + %plyr.packSet = 40; + bottomPrint(%plyr.client,"Telepad frequency set to: " @ %plyr.packSet,2,1); + %changed = true; + } + else if (%plyr.hasGen) { + %plyr.powerFreq = %plyr.powerFreq + %val; + if (%plyr.powerFreq > upperPowerFreq(%plyr)) + %plyr.powerFreq = 1; + if (%plyr.powerFreq < 1) + %plyr.powerFreq = upperPowerFreq(%plyr); + displayPowerFreq(%plyr); + %changed = true; + } + else if (%plyr.hasTripwire) { + %plyr.packSet = %plyr.packSet + %val; + if (%plyr.packSet > $packSettings["tripwire"]) + %plyr.packSet = 0; + if (%plyr.packSet < 0) + %plyr.packSet = $packSettings["tripwire"]; + %line = $packSetting["tripwire",%plyr.packSet]; + bottomPrint(%plyr.client,"Tripwire range set to " @ getWord(%line,0) @ " meters, " @ (getWord(%line,1) ? "field" : "beam") @ " mode.",2,1); + %changed = true; + } + else if (%plyr.hasEscapePod) { + %plyr.packSet = %plyr.packSet + %val; + if (%plyr.packSet > $packSettings["escapepod"]) + %plyr.packSet = 0; + if (%plyr.packSet < 0) + %plyr.packSet = $packSettings["escapepod"]; + displayEscapePodBoostPower(%plyr); + %changed = true; + } + else if (%plyr.hasMissileRack) { + %plyr.packSet = %plyr.packSet + %val; + if (%plyr.packSet > $packSettings["missilerack"]) + %plyr.packSet = 0; + if (%plyr.packSet < 0) + %plyr.packSet = $packSettings["missilerack"]; + %line = $packSetting["missilerack",%plyr.packSet]; + bottomPrint(%plyr.client,"Missile Rack set to " @ %line ,2,1); + %changed = true; + } + else if (%plyr.hasDoor) { +%plyr.packSet = %plyr.packSet + %val; +if (%plyr.packSet > $packSettings["Door"]) +%plyr.packSet = 0; +if (%plyr.packSet < 0) +%plyr.packSet = $packSettings["Door"]; +%line = $packSetting["Door",%plyr.packSet]; +bottomPrint(%plyr.client,"Door set to" SPC %line,2,1); +%changed = true; +} + return %changed; +} + + +//This function can be used by all "normal" packswitching packs. +//normal in a sense all modes are given in globals with the design +//given inside effectpacks.cs which is very simular to our current standarts +//The idea is the globals define all the variables and are linked by their pack image. +//This way all "plugin" data can be in the "pack".cs +//Alternative modes like the telleport freq change or nested modes like the effects pack, +//can easly be made by an alternative "::Changemode" function which again can be located +//inside "pack".cs file creating full plugin compability. + +function ShapeBaseImageData::ChangeMode(%data,%plyr,%val,%level) +{ +if (%level == 0) //regular pack settings + { + %image = %data.getName(); + + %settings = $packSettings[%image]; + + %plyr.packSet = %plyr.packSet + %val; + if (%plyr.packSet > getWord(%settings,0)) + %plyr.packSet = 0; + if (%plyr.packSet < 0) + %plyr.packSet = getWord(%settings,0); + %packname = GetWords(%settings,2,getWordCount(%settings)); + + %curset = $PackSetting[%image,%plyr.packSet]; + if (getWord(%settings,1) == -1) + %line = GetWords(%curset,0,getWordCount(%curset)); + else + %line = GetWords(%curset,0,getWord(%settings,1)); + + bottomPrint(%plyr.client,%packname SPC "set to"SPC %line,2,1); + return true; + } +else if (%level == 1) //expert settings + { + + %image = %data.getName(); + + %settings = $expertSettings[%image]; + + %plyr.expertSet = %plyr.expertSet + %val; + if (%plyr.expertSet > getWord(%settings,0)) + %plyr.expertSet = 0; + if (%plyr.expertSet < 0) + %plyr.expertSet = getWord(%settings,0); + + %packname = GetWords(%settings,2,getWordCount(%settings)); + %curset = $expertSetting[%image,%plyr.expertSet]; + if (getWord(%settings,1) == -1) + %line = GetWords(%curset,0,getWordCount(%curset)); + else + %line = GetWords(%curset,0,getWord(%settings,1)); + + bottomPrint(%plyr.client,%packname SPC "set to"SPC %line,2,1); + return true; + } +else if (%level == 2) //Weapon settings 1 + { + %image = %data.getName(); + + %settings = $weaponSettings1[%image]; + + %plyr.weaponSet1 = %plyr.weaponSet1 + %val; + if (%plyr.weaponSet1 > getWord(%settings,0)) + %plyr.weaponSet1 = 0; + if (%plyr.weaponSet1 < 0) + %plyr.weaponSet1 = getWord(%settings,0); + + %weaponname = GetWords(%settings,2,getWordCount(%settings)); + %curset = $weaponSetting1[%image,%plyr.weaponSet1]; + if (getWord(%settings,1) == -1) + %line = GetWords(%curset,0,getWordCount(%curset)); + else + %line = GetWords(%curset,0,getWord(%settings,1)); + + bottomPrint(%plyr.client,%weaponname SPC "set to"SPC %line,2,1); + return true; + } +else if (%level == 3) //Weapon settings 2 !!no nesting!! + { + %image = %data.getName(); + + %settings = $weaponSettings2[%image]; + + %plyr.weaponSet2 = %plyr.weaponSet2 + %val; + if (%plyr.weaponSet2 > getWord(%settings,0)) + %plyr.weaponSet2 = 0; + if (%plyr.weaponSet2 < 0) + %plyr.weaponSet2 = getWord(%settings,0); + + %weaponname = GetWords(%settings,2,getWordCount(%settings)); + %curset = $weaponSetting2[%image,%plyr.weaponSet2]; + if (getWord(%settings,1) == -1) + %line = GetWords(%curset,0,getWordCount(%curset)); + else + %line = GetWords(%curset,0,getWord(%settings,1)); + + bottomPrint(%plyr.client,%weaponname SPC "set to"SPC %line,2,1); + return true; + } +} + +//Neat lil settings mode fixer. +//It's optional.. but hey.. what the heck. +//Simply sees if the current setting is among the options.. if not .. set to option 1. + +//More usefull thought for specialized packs ;) ;) + +function ShapeBaseImageData::FixMode(%data,%plyr,%level) +{ +%image = %data.getName(); +if (%level == 0) //regular pack settings + { + %settings = $packSettings[%image]; + if (%plyr.packSet > getWord(%settings,0) || %plyr.packSet < 0) + %plyr.packSet = 0; + } +else if (%level == 1) //regular pack settings + { + %settings = $expertSettings[%image]; + if (%plyr.expertSet > getWord(%settings,0) || %plyr.expertSet < 0) + %plyr.expertSet = 0; + } +else if (%level == 2) //regular pack settings + { + %settings = $weaponSettings1[%image]; + if (%plyr.weaponSet1 > getWord(%settings,0) || %plyr.weaponSet1 < 0) + %plyr.weaponSet1 = 0; + } +else if (%level == 3) //regular pack settings + { + %settings = $weaponSettings2[%image]; + if (%plyr.weaponSet2 > getWord(%settings,0) || %plyr.weaponSet2 < 0) + %plyr.weaponSet2 = 0; + } +} diff --git a/scripts/libraries.cs b/scripts/libraries.cs new file mode 100644 index 0000000..86ac068 --- /dev/null +++ b/scripts/libraries.cs @@ -0,0 +1,362 @@ +//Contain basic data libraries. +//Soon to be updated with more usefull stuff. + +// NOTE - any changes here must be considered in expertlibraries.cs !!! + +//** New format of information ** + +$packSettings["spine"] = 7; +$packSetting["spine",0] = "0.5 0.5 1.5 1.5 meters in height"; +$packSetting["spine",1] = "0.5 0.5 4 4 meters in height"; +$packSetting["spine",2] = "0.5 0.5 8 8 meters in height"; +$packSetting["spine",3] = "0.5 0.5 40 40 meters in height"; +$packSetting["spine",4] = "0.5 0.5 160 160 meters in height"; +$packSetting["spine",5] = "0.5 6 160 auto adjusting"; +$packSetting["spine",6] = "0.5 8 160 pad"; +$packSetting["spine",7] = "0.5 8 160 wooden pad"; + +$packSettings["mspine"] = 7; +$packSetting["mspine",0] = "1 1 1 2 2 0.5 1 meters in height"; +$packSetting["mspine",1] = "1 1 4 2 2 0.5 4 meters in height"; +$packSetting["mspine",2] = "1 1 8 2 2 0.5 8 meters in height"; +$packSetting["mspine",3] = "1 1 40 2 2 0.5 40 meters in height"; +$packSetting["mspine",4] = "1 1 160 2 2 0.5 160 meters in height"; +$packSetting["mspine",5] = "1 8 160 2 2 0.5 auto adjusting"; +$packSetting["mspine",6] = "1 6 160 2 2 0.5 normal rings"; +$packSetting["mspine",7] = "1 8 160 8 8 0.5 platform rings"; + +$expertSettings["mspine"] = 1; +$expertSetting["mspine",0] = "Rings disabled"; +$expertSetting["mspine",1] = "Rings enabled"; + +$packSettings["floor"] = 5; +$packSetting["floor",0] = "10 10 20 10 10 10 10 meters wide"; +$packSetting["floor",1] = "20 20 20 20 20 20 20 meters wide"; +$packSetting["floor",2] = "30 30 20 30 30 30 30 meters wide"; +$packSetting["floor",3] = "40 40 20 40 40 40 40 meters wide"; +$packSetting["floor",4] = "50 50 20 50 50 50 50 meters wide"; +$packSetting["floor",5] = "60 60 20 60 60 60 60 meters wide"; + +$expertSettings["floor"] = 4; +$expertSetting["floor",0] = "1.5 meters in height"; +$expertSetting["floor",1] = "5 meters in height"; +$expertSetting["floor",2] = "10 meters in height"; +$expertSetting["floor",3] = "20 meters in height"; +$expertSetting["floor",4] = "40 meters in height"; + +$packSettings["walk"] = 12; +$packSetting["walk",0] = "0 flat"; +$packSetting["walk",1] = "5 Sloped 5 degrees up"; +$packSetting["walk",2] = "10 Sloped 10 degrees up"; +$packSetting["walk",3] = "20 Sloped 20 degrees up"; +$packSetting["walk",4] = "45 Sloped 45 degrees up"; +$packSetting["walk",5] = "60 Sloped 60 degrees up"; +$packSetting["walk",6] = "90 Sloped 90 degrees up"; +$packSetting["walk",7] = "-5 Sloped 5 degrees down"; +$packSetting["walk",8] = "-10 Sloped 10 degrees down"; +$packSetting["walk",9] = "-20 Sloped 20 degrees down"; +$packSetting["walk",10] = "-45 Sloped 45 degrees down"; +$packSetting["walk",11] = "-60 Sloped 60 degrees down"; +$packSetting["walk",12] = "-90 Sloped 90 degrees down"; + +$expertSettings["walk"] = 3; +$expertSetting["walk",0] = "Normal walkway"; +$expertSetting["walk",1] = "No-flicker walkway"; +$expertSetting["walk",2] = "Double width walkway"; +$expertSetting["walk",3] = "Double height walkway"; + +$packSettings["blast"] = 3; +$packSetting["blast",0] = "deploy from inside"; +$packSetting["blast",1] = "deploy in frame"; +$packSetting["blast",2] = "deploy from outside"; +$packSetting["blast",3] = "deploy full thickness"; + +$expertSettings["blast"] = 1; +$expertSetting["blast",0] = "Normal Blast Wall"; +$expertSetting["blast",1] = "Multiple Blast Walls"; + +$packSettings["forcefield"] = 20; +$packSetting["forcefield",0] = "0.5 8 160 (7) Force field set to solid white"; +$packSetting["forcefield",1] = "0.5 8 160 (6) Force field set to solid red"; +$packSetting["forcefield",2] = "0.5 8 160 (5) Force field set to solid green"; +$packSetting["forcefield",3] = "0.5 8 160 (4) Force field set to solid blue"; +$packSetting["forcefield",4] = "0.5 8 160 (3) Force field set to solid cyan"; +$packSetting["forcefield",5] = "0.5 8 160 (2) Force field set to solid magenta"; +$packSetting["forcefield",6] = "0.5 8 160 (1) Force field set to solid yellow"; +$packSetting["forcefield",7] = "0.5 8 160 (7) Force field set to team-pass white"; +$packSetting["forcefield",8] = "0.5 8 160 (6) Force field set to team-pass red"; +$packSetting["forcefield",9] = "0.5 8 160 (5) Force field set to team-pass green"; +$packSetting["forcefield",10] = "0.5 8 160 (4) Force field set to team-pass blue"; +$packSetting["forcefield",11] = "0.5 8 160 (3) Force field set to team-pass cyan"; +$packSetting["forcefield",12] = "0.5 8 160 (2) Force field set to team-pass magenta"; +$packSetting["forcefield",13] = "0.5 8 160 (1) Force field set to team-pass yellow"; +$packSetting["forcefield",14] = "0.5 8 160 (7) Force field set to all-pass white"; +$packSetting["forcefield",15] = "0.5 8 160 (6) Force field set to all-pass red"; +$packSetting["forcefield",16] = "0.5 8 160 (5) Force field set to all-pass green"; +$packSetting["forcefield",17] = "0.5 8 160 (4) Force field set to all-pass blue"; +$packSetting["forcefield",18] = "0.5 8 160 (3) Force field set to all-pass cyan"; +$packSetting["forcefield",19] = "0.5 8 160 (2) Force field set to all-pass magenta"; +$packSetting["forcefield",20] = "0.5 8 160 (1) Force field set to all-pass yellow"; + +$expertSettings["forcefield"] = 3; +$expertSetting["forcefield",0] = "Normal force field"; +$expertSetting["forcefield",1] = "Cubic-replace force field"; +$expertSetting["forcefield",2] = "Normal force field - no slowdown"; +$expertSetting["forcefield",3] = "Cubic-replace force field - no slowdown"; + +$packSettings["gravfield"] = 4; +$packSetting["gravfield",0] = "4.25 8 500 normal slow"; +$packSetting["gravfield",1] = "4.25 8 500 normal fast"; +$packSetting["gravfield",2] = "4.25 8 500 reverse slow"; +$packSetting["gravfield",3] = "4.25 8 500 reverse fast"; +$packSetting["gravfield",4] = "4.25 8 500 zero gravity"; +// +$packSetting["gravfield",5] = "4.25 8 500 fastfield"; +$packSetting["gravfield",6] = "4.25 8 500 super fastfield"; + +$expertSettings["gravfield"] = 2; +$expertSetting["gravfield",0] = "Normal gravity field"; +$expertSetting["gravfield",1] = "Cubic-replace gravity field (player's orientation)"; +$expertSetting["gravfield",2] = "Cubic-replace gravity field (object's orientation)"; + +$packSettings["jumpad"] = 3; +$packSetting["jumpad",0] = "1000 10 boost"; +$packSetting["jumpad",1] = "2500 25 boost"; +$packSetting["jumpad",2] = "5000 50 boost"; +$packSetting["jumpad",3] = "10000 100 boost"; + +$packSettings["tree"] = 13; +$packSetting["tree",0] = "normal 1"; +$packSetting["tree",1] = "normal 2"; +$packSetting["tree",2] = "normal 3"; +$packSetting["tree",3] = "normal 4"; +$packSetting["tree",4] = "greywood 1"; +$packSetting["tree",5] = "greywood 2"; +$packSetting["tree",6] = "greywood 3"; +$packSetting["tree",7] = "greywood 4"; +$packSetting["tree",8] = "greywood 5"; +$packSetting["tree",9] = "cactus 1"; +$packSetting["tree",10] = "cactus 2"; +$packSetting["tree",11] = "misc 1"; +$packSetting["tree",12] = "misc 2"; +$packSetting["tree",13] = "pod 1"; + +$expertSettings["tree"] = 14; +$expertSetting["tree",0] = "0.0625"; +$expertSetting["tree",1] = "0.125"; +$expertSetting["tree",2] = "0.25"; +$expertSetting["tree",3] = "0.5"; +$expertSetting["tree",4] = "0.75"; +$expertSetting["tree",5] = "1"; +$expertSetting["tree",6] = "2"; +$expertSetting["tree",7] = "3"; +$expertSetting["tree",8] = "4"; +$expertSetting["tree",9] = "5"; +$expertSetting["tree",10] = "6"; +$expertSetting["tree",11] = "7"; +$expertSetting["tree",12] = "8"; +$expertSetting["tree",13] = "9"; +$expertSetting["tree",14] = "10"; + +$packSettings["crate"] = 12; +$packSetting["crate",0] = "(1) back pack"; +$packSetting["crate",1] = "(2) small containment"; +$packSetting["crate",2] = "(3) large containment"; +$packSetting["crate",3] = "(4) compressor"; +$packSetting["crate",4] = "(5) tubes"; +$packSetting["crate",5] = "(6) quantum battery"; +$packSetting["crate",6] = "(7) proton accelerator"; +$packSetting["crate",7] = "(8) cargo crate"; +$packSetting["crate",8] = "(9) magnetic cooler"; +$packSetting["crate",9] = "(10) recycle unit"; +$packSetting["crate",10] = "(11) fuel cannister"; +$packSetting["crate",11] = "(12) wooden T2 box"; +$packSetting["crate",12] = "(13) plasma router"; + +$packSettings["decoration"] = 15; +$packSetting["decoration",0] = "(1) banner unity"; +$packSetting["decoration",1] = "(2) banner strength"; +$packSetting["decoration",2] = "(3) banner honor"; +$packSetting["decoration",3] = "(4) dead light armor"; +$packSetting["decoration",4] = "(5) dead medium armor"; +$packSetting["decoration",5] = "(6) dead heavy armor"; +$packSetting["decoration",6] = "(7) statue base"; +$packSetting["decoration",7] = "(8) light male statue"; +$packSetting["decoration",8] = "(9) light female statue"; +$packSetting["decoration",9] = "(10) heavy male statue"; +$packSetting["decoration",10] = "(11) beowulf wreck"; +$packSetting["decoration",11] = "(12) shrike wreck"; +$packSetting["decoration",12] = "(13) billboard 1"; +$packSetting["decoration",13] = "(14) billboard 2"; +$packSetting["decoration",14] = "(15) billboard 3"; +$packSetting["decoration",15] = "(16) billboard 4"; + +$packSettings["logoprojector"] = 7; +$packSetting["logoprojector",0] = "your teams logo"; +$packSetting["logoprojector",1] = "Storm"; +$packSetting["logoprojector",2] = "Inferno"; +$packSetting["logoprojector",3] = "Starwolf"; +$packSetting["logoprojector",4] = "Diamond Sword"; +$packSetting["logoprojector",5] = "Blood Eagle"; +$packSetting["logoprojector",6] = "Phoenix"; +$packSetting["logoprojector",7] = "Bioderm"; + +$packSettings["switch"] = 6; +$packSetting["switch",0] = "5"; +$packSetting["switch",1] = "10"; +$packSetting["switch",2] = "25"; +$packSetting["switch",3] = "50"; +$packSetting["switch",4] = "100"; +$packSetting["switch",5] = "150"; +$packSetting["switch",6] = "200"; + +$expertSettings["switch"] = 2; +$expertSetting["switch",0] = "Normal switch"; +$expertSetting["switch",1] = "Timed switch on"; +$expertSetting["switch",2] = "Timed switch off"; + +$packSettings["light"] = 13; +$packSetting["light",0] = "(7) white"; +$packSetting["light",1] = "(6) red"; +$packSetting["light",2] = "(5) green"; +$packSetting["light",3] = "(4) blue"; +$packSetting["light",4] = "(3) cyan"; +$packSetting["light",5] = "(2) magenta"; +$packSetting["light",6] = "(1) yellow"; +$packSetting["light",7] = "(7) strobe white"; +$packSetting["light",8] = "(6) strobe red"; +$packSetting["light",9] = "(5) strobe green"; +$packSetting["light",10] = "(4) strobe blue"; +$packSetting["light",11] = "(3) strobe cyan"; +$packSetting["light",12] = "(2) strobe magenta"; +$packSetting["light",13] = "(1) strobe yellow"; + +$packSettings["Door"] = 7; +$packSetting["Door",0] = "Normal Door"; +$packSetting["Door",1] = "Toggle Door"; +$packSetting["Door",2] = "Power Change Normal Door"; +$packSetting["Door",3] = "Power Change Toggle Door"; +$packSetting["Door",4] = "contact door"; +$packSetting["Door",5] = "contact door owner door"; +$packSetting["Door",6] = "contact door admin door"; +$packSetting["Door",7] = "contact door if powered will be locked"; + +$expertSettings["Door"] = 5; +$expertSetting["Door",0] = "0 Seconds"; +$expertSetting["Door",1] = "0.5 Seconds"; +$expertSetting["Door",2] = "1 Second"; +$expertSetting["Door",3] = "2 Seconds"; +$expertSetting["Door",4] = "3 Seconds"; +$expertSetting["Door",5] = "4 Seconds"; + +$packSettings["tripwire"] = 13; +$packSetting["tripwire",0] = "5 0"; +$packSetting["tripwire",1] = "10 0"; +$packSetting["tripwire",2] = "25 0"; +$packSetting["tripwire",3] = "50 0"; +$packSetting["tripwire",4] = "100 0"; +$packSetting["tripwire",5] = "150 0"; +$packSetting["tripwire",6] = "200 0"; +$packSetting["tripwire",7] = "5 1"; +$packSetting["tripwire",8] = "10 1"; +$packSetting["tripwire",9] = "25 1"; +$packSetting["tripwire",10] = "50 1"; +$packSetting["tripwire",11] = "100 1"; +$packSetting["tripwire",12] = "150 1"; +$packSetting["tripwire",13] = "200 1"; + +$expertSettings["tripwire"] = 5; +$expertSetting["tripwire",0] = "Normal toggle on"; +$expertSetting["tripwire",1] = "Normal toggle off"; +$expertSetting["tripwire",2] = "Only turn on"; +$expertSetting["tripwire",3] = "Only turn off"; +$expertSetting["tripwire",4] = "Timed turn off"; +$expertSetting["tripwire",5] = "Timed turn on"; + +$packSettings["escapepod"] = 7; +$packSetting["escapepod",0] = "1875"; // 12.25% +$packSetting["escapepod",1] = "3750"; // 25% +$packSetting["escapepod",2] = "5625"; // 37.5% +$packSetting["escapepod",3] = "7500"; // 50% +$packSetting["escapepod",4] = "9375"; // 62.5% +$packSetting["escapepod",5] = "11250"; // 75% +$packSetting["escapepod",6] = "13125"; // 87.5% +$packSetting["escapepod",7] = "15000"; // 100% + +$expertSettings["telepad"] = 3; +$expertSetting["telepad",0] = "team only"; +$expertSetting["telepad",1] = "any team"; +$expertSetting["telepad",2] = "only transmit"; +$expertSetting["telepad",3] = "only receive"; + +$packSettings["missilerack"] = 1; +$packSetting["missilerack",0] = "dumbfire missiles"; +$packSetting["missilerack",1] = "seeking missiles"; + +$packSettings["VehiclePadPack"] = 2; +$packSetting["VehiclePadPack",0] = "Regular Vehicle Pad"; +$packSetting["VehiclePadPack",1] = "Modern Vehicle Pad"; +$packSetting["VehiclePadPack",2] = "Zigma's Smoke Shack"; + + +//i modified the weapon mode change to work more like the pack settings +//easyer to edit and work whit +$WeaponSettings["modifier0"] = 0; +$WeaponSetting["modifier0",0] = "merge pieces"; + +$WeaponSettings["modifier1"] = 18; +$WeaponSetting["modifier1",0] = "DeployedSpine lsb";//0.125 0.166666 1 +$WeaponSetting["modifier1",1] = "DeployedMSpine msb";//0.125 0.166666 1 +$WeaponSetting["modifier1",2] = "DeployedwWall WalkWay";//0.125 0.166666 1 +$WeaponSetting["modifier1",3] = "DeployedWall Bwall";//0.125 0.166666 1 +$WeaponSetting["modifier1",4] = "DeployedSpine2 Dark Pad";//0.125 0.166666 1 +$WeaponSetting["modifier1",5] = "DeployedCrate0 (crate1) back pack";//0.5 1 0.925 +$WeaponSetting["modifier1",6] = "DeployedCrate1 (crate2) small containment";//0.16 0.5 0.488 +$WeaponSetting["modifier1",7] = "DeployedCrate2 (crate3) large containment";//0.1 0.25 0.25 +$WeaponSetting["modifier1",8] = "DeployedCrate3 (crate4) compressor";//1 1 1 +$WeaponSetting["modifier1",9] = "DeployedCrate4 (crate5) tubes";//0.5 0.5 0.48 +$WeaponSetting["modifier1",10] = "DeployedCrate5 (crate6) quantum battery";//0.25 0.25 0.25 +$WeaponSetting["modifier1",11] = "DeployedCrate6 (crate7) proton accelerator";//0.25 0.5 0.5 +$WeaponSetting["modifier1",12] = "DeployedCrate7 (crate8) cargo crate";//0.1255 0.249 0.246 +$WeaponSetting["modifier1",13] = "DeployedCrate8 (crate9) magnetic cooler";//0.0835 0.167 0.1666 +$WeaponSetting["modifier1",14] = "DeployedCrate9 (crate10) recycle unit";//1.25 1.25 0.48; +$WeaponSetting["modifier1",15] = "DeployedCrate10 (crate11) fuel cannister";//0.834 0.834 0.336 +$WeaponSetting["modifier1",16] = "DeployedCrate11 (crate12) wooden T2 box"; +$WeaponSetting["modifier1",17] = "DeployedCrate12 (crate13) plasma router"; +$WeaponSetting["modifier1",18] = "DeployedDecoration6 (deco1) statue base"; + +$WeaponSettings["modifier2"] = 7; +$WeaponSetting["modifier2",0] = "+whole scale"; +$WeaponSetting["modifier2",1] = "+x axis scale"; +$WeaponSetting["modifier2",2] = "+y axis scale"; +$WeaponSetting["modifier2",3] = "+z axis scale"; +$WeaponSetting["modifier2",4] = "-whole scale"; +$WeaponSetting["modifier2",5] = "-x axis scale"; +$WeaponSetting["modifier2",6] = "-y axis scale"; +$WeaponSetting["modifier2",7] = "-z axis scale"; + +$WeaponSettings["modifier3"] = 7; +$WeaponSetting["modifier3",0] = "move up"; +$WeaponSetting["modifier3",1] = "move down"; +$WeaponSetting["modifier3",2] = "+x axis move"; +$WeaponSetting["modifier3",3] = "-x axis move"; +$WeaponSetting["modifier3",4] = "+y axis move"; +$WeaponSetting["modifier3",5] = "-y axis move"; +$WeaponSetting["modifier3",6] = "+z axis move"; +$WeaponSetting["modifier3",7] = "-z axis move"; + +$WeaponSettings["modifier4"] = 3; +$WeaponSetting["modifier4",0] = "0.1"; +$WeaponSetting["modifier4",1] = "0.01"; +$WeaponSetting["modifier4",2] = "0.001"; +$WeaponSetting["modifier4",3] = "1"; + +//list of smaller list +$WeaponSettings2["modifier"] = 5;//format :max mode +$WeaponSetting2["modifier",0] = $WeaponSettings["modifier0"] SPC"Merge Pieces"; +$WeaponSetting2["modifier",1] = $WeaponSettings["modifier1"] SPC"Swap Pad Texture"; +$WeaponSetting2["modifier",2] = $packSettings["forcefield"] SPC"Swap Force Field Texture"; +$WeaponSetting2["modifier",3] = $WeaponSettings["modifier2"] SPC"Scale Pieces"; +$WeaponSetting2["modifier",4] = $WeaponSettings["modifier3"] SPC"Nudge Pieces"; +$WeaponSetting2["modifier",5] = $WeaponSettings["modifier4"] SPC"Modifier Scaler"; + diff --git a/scripts/message.cs b/scripts/message.cs new file mode 100644 index 0000000..10d8e80 --- /dev/null +++ b/scripts/message.cs @@ -0,0 +1,422 @@ +$MaxMessageWavLength = 5200; + +function addMessageCallback(%msgType, %func) +{ + for(%i = 0; (%afunc = $MSGCB[%msgType, %i]) !$= ""; %i++) + { + // only add each callback once + if(%afunc $= %func) + return; + } + $MSGCB[%msgType, %i] = %func; +} + +function messagePump(%msgType, %msgString, %a1, %a2, %a3, %a4, %a5, %a6, %a7 ,%a8, %a9, %a10) +{ + clientCmdServerMessage(%msgType, %msgString, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10); +} + +function clientCmdServerMessage(%msgType, %msgString, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10) +{ + %tag = getWord(%msgType, 0); + for(%i = 0; (%func = $MSGCB["", %i]) !$= ""; %i++) + call(%func, %msgType, %msgString, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10); + + if(%tag !$= "") + for(%i = 0; (%func = $MSGCB[%tag, %i]) !$= ""; %i++) + call(%func, %msgType, %msgString, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10); +} + +function defaultMessageCallback(%msgType, %msgString, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10) +{ + if ( %msgString $= "" ) + return; + + %message = detag( %msgString ); + // search for wav tag marker + %wavStart = strstr( %message, "~w" ); + if ( %wavStart != -1 ) + { + %wav = getSubStr( %message, %wavStart + 2, 1000 ); + %wavLengthMS = alxGetWaveLen( %wav ); + if ( %wavLengthMS <= $MaxMessageWavLength ) + { + %handle = alxCreateSource( AudioChat, %wav ); + alxPlay( %handle ); + } + else + error( "WAV file \"" @ %wav @ "\" is too long! **" ); + + %message = getSubStr( %message, 0, %wavStart ); + if ( %message !$= "" ) + addMessageHudLine( %message ); + } + else + addMessageHudLine( %message ); +} + +//-------------------------------------------------------------------------- +function handleClientJoin(%msgType, %msgString, %clientName, %clientId, %targetId, %isAI, %isAdmin, %isSuperAdmin, %isSmurf, %guid) +{ + logEcho("got client join: " @ detag(%clientName) @ " : " @ %clientId); + + //create the player list group, and add it to the ClientConnectionGroup... + if(!isObject("PlayerListGroup")) + { + %newGroup = new SimGroup("PlayerListGroup"); + ClientConnectionGroup.add(%newGroup); + } + + %player = new ScriptObject() + { + className = "PlayerRep"; + name = detag(%clientName); + guid = %guid; + clientId = %clientId; + targetId = %targetId; + teamId = 0; // start unassigned + score = 0; + ping = 0; + packetLoss = 0; + chatMuted = false; + canListen = false; + voiceEnabled = false; + isListening = false; + isBot = %isAI; + isAdmin = %isAdmin; + isSuperAdmin = %isSuperAdmin; + isSmurf = %isSmurf; + }; + PlayerListGroup.add(%player); + $PlayerList[%clientId] = %player; + + if ( !%isAI ) + getPlayerPrefs(%player); + lobbyUpdatePlayer( %clientId ); +} + +function handleClientDrop( %msgType, %msgString, %clientName, %clientId ) +{ + logEcho("got client drop: " @ detag(%clientName) @ " : " @ %clientId); + + %player = $PlayerList[%clientId]; + if( %player ) + { + %player.delete(); + $PlayerList[%clientId] = ""; + lobbyRemovePlayer( %clientId ); + } +} + +function handleClientJoinTeam( %msgType, %msgString, %clientName, %teamName, %clientId, %teamId ) +{ + %player = $PlayerList[%clientId]; + if( %player ) + { + %player.teamId = %teamId; + lobbyUpdatePlayer( %clientId ); + } +} + +function handleClientNameChanged( %msgType, %msgString, %oldName, %newName, %clientId ) +{ + %player = $PlayerList[%clientId]; + if( %player ) + { + %player.name = detag( %newName ); + lobbyUpdatePlayer( %clientId ); + } +} + +addMessageCallback("", defaultMessageCallback); +addMessageCallback('MsgClientJoin', handleClientJoin); +addMessageCallback('MsgClientDrop', handleClientDrop); +addMessageCallback('MsgClientJoinTeam', handleClientJoinTeam); +addMessageCallback('MsgClientNameChanged', handleClientNameChanged); + +//--------------------------------------------------------------------------- +// Client chat'n +//--------------------------------------------------------------------------- +function isClientChatMuted(%client) +{ + %player = $PlayerList[%client]; + if(%player) + return(%player.chatMuted ? true : false); + return(true); +} + +//--------------------------------------------------------------------------- +function clientCmdChatMessage(%sender, %voice, %pitch, %msgString, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10) +{ + %message = detag( %msgString ); + %voice = detag( %voice ); + + if ( ( %message $= "" ) || isClientChatMuted( %sender ) ) + return; + + // search for wav tag marker + %wavStart = strstr( %message, "~w" ); + if ( %wavStart == -1 ) + addMessageHudLine( %message ); + else + { + %wav = getSubStr(%message, %wavStart + 2, 1000); + if (%voice !$= "") + %wavFile = "voice/" @ %voice @ "/" @ %wav @ ".wav"; + else + %wavFile = %wav; + + //only play voice files that are < 5000ms in length + if (%pitch < 0.5 || %pitch > 2.0) + %pitch = 1.0; + %wavLengthMS = alxGetWaveLen(%wavFile) * %pitch; + if (%wavLengthMS < $MaxMessageWavLength ) + { + if ( $ClientChatHandle[%sender] != 0 ) + alxStop( $ClientChatHandle[%sender] ); + $ClientChatHandle[%sender] = alxCreateSource( AudioChat, %wavFile ); + + //pitch the handle + if (%pitch != 1.0) + alxSourcef($ClientChatHandle[%sender], "AL_PITCH", %pitch); + alxPlay( $ClientChatHandle[%sender] ); + } + else + error( "** WAV file \"" @ %wavFile @ "\" is too long! **" ); + + %message = getSubStr(%message, 0, %wavStart); + addMessageHudLine(%message); + } +} + +//--------------------------------------------------------------------------- +function clientCmdCannedChatMessage( %sender, %msgString, %name, %string, %keys, %voiceTag, %pitch ) +{ + %message = detag( %msgString ); + %voice = detag( %voiceTag ); + if ( $defaultVoiceBinds ) + clientCmdChatMessage( %sender, %voice, %pitch, "[" @ %keys @ "]" SPC %message ); + else + clientCmdChatMessage( %sender, %voice, %pitch, %message ); +} + +//--------------------------------------------------------------------------- +// silly spam protection... +$SPAM_PROTECTION_PERIOD = 10000; +$SPAM_MESSAGE_THRESHOLD = 4; +$SPAM_PENALTY_PERIOD = 10000; +$SPAM_MESSAGE = '\c3FLOOD PROTECTION:\cr You must wait another %1 seconds.'; + +function GameConnection::spamMessageTimeout(%this) +{ + if(%this.spamMessageCount > 0) + %this.spamMessageCount--; +} + +function GameConnection::spamReset(%this) +{ + %this.isSpamming = false; +} + +function spamAlert(%client) +{ + if($Host::FloodProtectionEnabled != true) + return(false); + + if(!%client.isSpamming && (%client.spamMessageCount >= $SPAM_MESSAGE_THRESHOLD)) + { + %client.spamProtectStart = getSimTime(); + %client.isSpamming = true; + %client.schedule($SPAM_PENALTY_PERIOD, spamReset); + } + + if(%client.isSpamming) + { + %wait = mFloor(($SPAM_PENALTY_PERIOD - (getSimTime() - %client.spamProtectStart)) / 1000); + messageClient(%client, "", $SPAM_MESSAGE, %wait); + return(true); + } + + %client.spamMessageCount++; + %client.schedule($SPAM_PROTECTION_PERIOD, spamMessageTimeout); + return(false); +} + +function chatMessageClient( %client, %sender, %voiceTag, %voicePitch, %msgString, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10 ) +{ + //see if the client has muted the sender + if ( !%client.muted[%sender] ) + commandToClient( %client, 'ChatMessage', %sender, %voiceTag, %voicePitch, %msgString, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10 ); +} + +function cannedChatMessageClient( %client, %sender, %msgString, %name, %string, %keys ) +{ + if ( !%client.muted[%sender] ) + commandToClient( %client, 'CannedChatMessage', %sender, %msgString, %name, %string, %keys, %sender.voiceTag, %sender.voicePitch ); +} + +function chatMessageTeam( %sender, %team, %msgString, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10 ) +{ + //chat Echoing and logging + %echoStr = %a2; + %echoStr=strreplace(%echoStr,"\c5",""); + %echoStr=strreplace(%echoStr,"\c4",""); + %echoStr=strreplace(%echoStr,"\c3",""); + %echoStr=strreplace(%echoStr,"\c2",""); + %echoStr=strreplace(%echoStr,"\c1",""); + if ($Construction::Logging::EchoChat) + echo(getTaggedString(%sender.name) @ ":" SPC %echoStr); + if ($Construction::Logging::LogChat) + serverChatLog(%sender, %echoStr); + + if ( ( %msgString $= "" ) || spamAlert( %sender ) ) + return; + %count = ClientGroup.getCount(); + for ( %i = 0; %i < %count; %i++ ) + { + %obj = ClientGroup.getObject( %i ); + if ( %obj.team == %sender.team ) + chatMessageClient( %obj, %sender, %sender.voiceTag, %sender.voicePitch, %msgString, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10 ); + } +} + +function cannedChatMessageTeam( %sender, %team, %msgString, %name, %string, %keys ) +{ + if ( ( %msgString $= "" ) || spamAlert( %sender ) ) + return; + + %count = ClientGroup.getCount(); + for ( %i = 0; %i < %count; %i++ ) + { + %obj = ClientGroup.getObject( %i ); + if ( %obj.team == %sender.team ) + cannedChatMessageClient( %obj, %sender, %msgString, %name, %string, %keys ); + } +} + +function chatMessageAll( %sender, %msgString, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10 ) +{ +if ( ( %msgString $= "" ) || spamAlert( %sender ) ) +return; +%count = ClientGroup.getCount(); + +if (getSubStr(%a2, 0, 1) !$= "/") { +for ( %i = 0; %i < %count; %i++ ) +{ +%obj = ClientGroup.getObject( %i ); +if(%sender.team != 0) +chatMessageClient( %obj, %sender, %sender.voiceTag, %sender.voicePitch, %msgString, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10 ); +else +{ +// message sender is an observer -- only send message to other observers +if(%obj.team == %sender.team || %obj.isAdmin || %obj.isSuperAdmin) +chatMessageClient( %obj, %sender, %sender.voiceTag, %sender.voicePitch, %msgString, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10 ); +} +} +} +if(getSubStr(%a2, 0, 1) $= "/") +chatcommands(%sender,%a2); +} + +function cannedChatMessageAll( %sender, %msgString, %name, %string, %keys ) +{ + if ( ( %msgString $= "" ) || spamAlert( %sender ) ) + return; + + %count = ClientGroup.getCount(); + for ( %i = 0; %i < %count; %i++ ) + cannedChatMessageClient( ClientGroup.getObject(%i), %sender, %msgString, %name, %string, %keys ); +} + +//--------------------------------------------------------------------------- +function messageClient(%client, %msgType, %msgString, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10, %a11, %a12, %a13) +{ + commandToClient(%client, 'ServerMessage', %msgType, %msgString, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10, %a11, %a12, %a13); +} + +function messageTeam(%team, %msgType, %msgString, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10, %a11, %a12, %a13) +{ + %count = ClientGroup.getCount(); + for(%cl= 0; %cl < %count; %cl++) + { + %recipient = ClientGroup.getObject(%cl); + if(%recipient.team == %team) + messageClient(%recipient, %msgType, %msgString, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10, %a11, %a12, %a13); + } +} + +function messageTeamExcept(%client, %msgType, %msgString, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10, %a11, %a12, %a13) +{ + %team = %client.team; + %count = ClientGroup.getCount(); + for(%cl= 0; %cl < %count; %cl++) + { + %recipient = ClientGroup.getObject(%cl); + if((%recipient.team == %team) && (%recipient != %client)) + messageClient(%recipient, %msgType, %msgString, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10, %a11, %a12, %a13); + } +} + +function messageAll(%msgType, %msgString, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10, %a11, %a12, %a13) +{ + %count = ClientGroup.getCount(); + for(%cl = 0; %cl < %count; %cl++) + { + %client = ClientGroup.getObject(%cl); + messageClient(%client, %msgType, %msgString, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10, %a11, %a12, %a13); + } +} + +function messageAllExcept(%client, %team, %msgtype, %msgString, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10, %a11, %a12, %a13) +{ + //can exclude a client, a team or both. A -1 value in either field will ignore that exclusion, so + //messageAllExcept(-1, -1, $Mesblah, 'Blah!'); will message everyone (since there shouldn't be a client -1 or client on team -1). + %count = ClientGroup.getCount(); + for(%cl= 0; %cl < %count; %cl++) + { + %recipient = ClientGroup.getObject(%cl); + if((%recipient != %client) && (%recipient.team != %team)) + messageClient(%recipient, %msgType, %msgString, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10, %a11, %a12, %a13); + } +} + +//--------------------------------------------------------------------------- +// functions to support repair messaging +//--------------------------------------------------------------------------- +function clientCmdTeamRepairMessage(%msgType, %msgString, %a1, %a2, %a3, %a4, %a5, %a6) +{ + if(!$pref::ignoreTeamRepairMessages) + clientCmdServerMessage(%msgType, %msgString, %a1, %a2, %a3, %a4, %a5, %a6); +} + +function teamRepairMessage(%client, %msgType, %msgString, %a1, %a2, %a3, %a4, %a5, %a6) +{ + %team = %client.team; + + %count = ClientGroup.getCount(); + for(%i = 0; %i < %count; %i++) + { + %recipient = ClientGroup.getObject(%cl); + if((%recipient.team == %team) && (%recipient != %client)) + commandToClient(%recipient, 'TeamRepairMessage', %msgType, %msgString, %a1, %a2, %a3, %a4, %a5, %a6); + } +} + +//--------------------------------------- +//Chat Logging: Electricutioner + + +function serverChatLog(%sender, %message) +{ + %logname = getTaggedString(%sender.name); + %logname = strreplace(%logname,"\x10",""); + %logname = strreplace(%logname,"\x11",""); + %logname = strreplace(%logname,"\c8",""); + %logname = strreplace(%logname,"\c7",""); + %logname = strreplace(%logname,"\c6",""); + + %logExport = formatTimeString(yy) @ "/" @ formatTimeString(mm) @ "/" @ formatTimeString(dd); + %logExport = %logExport SPC formatTimeString(h) @ ":" @ formatTimeString(n) @ "." @ formatTimeString(s) SPC formatTimeString(a); + %logExport = %logExport SPC %logname @ ":" SPC %message; + exportToLog(%logexport, "Logs/Chat/" @ formatTimeString(yy) @ "-" @ formatTimeString(mm) @ "-" @ formatTimeString(dd) @ ".log"); +} diff --git a/scripts/nerf.cs b/scripts/nerf.cs new file mode 100644 index 0000000..a279998 --- /dev/null +++ b/scripts/nerf.cs @@ -0,0 +1,121 @@ +// Nerf + +// Original anim idea from Bones' Dance Inducer gun + +// Set up defaults for nonexisting vars + +// Init handled by server.cs +//if ($Host::Nerf::Enabled $= "") +// $Host::Nerf::Enabled = "1"; // Enable nerf weapons + +if ($Host::Nerf::DanceAnim $= "") + $Host::Nerf::DanceAnim = "1"; // Enable dance anim for nerf weapons +if ($Host::Nerf::DeathAnim $= "") + $Host::Nerf::DeathAnim = "0"; // Enable death anim for nerf weapons +if ($Host::Nerf::Prison $= "") + $Host::Nerf::Prison = "0"; // Enable prison for nerf weapons +if ($Host::Nerf::PrisonTime $= "") + $Host::Nerf::PrisonTime = "10"; // Time to jail players with nerf weapons + +function applyNerf(%targetObject,%sourceObject,%position) { + if (%targetObject.getClassName() $= "Player") { + serverPlay3D(blasterExpSound,%position); + if ($Host::Nerf::DanceAnim == true && !$Host::Nerf::DeathAnim == true) + %targetObject.setActionThread("Cel" @ getRandom(8)+1,true); + if ($Host::Nerf::DeathAnim == true) + %targetObject.setActionThread("Death" @ getRandom(10)+1,true); + if ($Host::Prison::Enabled == true && $Host::Nerf::Prison == true && $Host::Nerf::PrisonTime > 0 + && isObject(%targetObject.client) // && isObject(%sourceObject) + && !%targetObject.client.isJailed) { + %emitter = new ParticleEmissionDummy(NerfJailEmitter) { + position = %position; + rotation = "1 0 0 0"; + scale = "1 1 1"; + dataBlock = "defaultEmissionDummy"; + emitter = "PlasmaBarrelCrescentEmitter"; + velocity = "1"; + }; + MissionCleanup.add(%emitter); // Well.. + %emitter.schedule(500,"delete"); + jailPlayer(%targetObject.client,false,$Host::Nerf::PrisonTime); + messageAll('msgClient','\c2%1 put %2 in jail for %3 seconds.',%sourceObject.client.name,%targetObject.client.name,$Host::Nerf::PrisonTime); + } + } +} + +function nerfEnable () { + $Host::Nerf::Enabled = 1; + + LightMaleHumanArmor.maxNerfGun = 1; + LightMaleHumanArmor.maxNerfBallLauncher = 1; + LightFemaleHumanArmor.maxNerfGun = 1; + LightFemaleHumanArmor.maxNerfBallLauncher = 1; + LightMaleBiodermArmor.maxNerfGun = 1; + LightMaleBiodermArmor.maxNerfBallLauncher = 1; + + MediumMaleHumanArmor.maxNerfGun = 1; + MediumMaleHumanArmor.maxNerfBallLauncher = 1; + MediumFemaleHumanArmor.maxNerfGun = 1; + MediumFemaleHumanArmor.maxNerfBallLauncher = 1; + MediumMaleBiodermArmor.maxNerfGun = 1; + MediumMaleBiodermArmor.maxNerfBallLauncher = 1; + + HeavyMaleHumanArmor.maxNerfGun = 1; + HeavyMaleHumanArmor.maxNerfBallLauncher = 1; + HeavyFemaleHumanArmor.maxNerfGun = 1; + HeavyFemaleHumanArmor.maxNerfBallLauncher = 1; + HeavyMaleBiodermArmor.maxNerfGun = 1; + HeavyMaleBiodermArmor.maxNerfBallLauncher = 1; + + PureMaleHumanArmor.maxNerfGun = 1; + PureMaleHumanArmor.maxNerfBallLauncher = 1; + PureFemaleHumanArmor.maxNerfGun = 1; + PureFemaleHumanArmor.maxNerfBallLauncher = 1; + PureMaleBiodermArmor.maxNerfGun = 1; + PureMaleBiodermArmor.maxNerfBallLauncher = 1; +} + +function nerfDisable () { + $Host::Nerf::Enabled = 0; + + LightMaleHumanArmor.maxNerfGun = 0; + LightMaleHumanArmor.maxNerfBallLauncher = 0; + LightFemaleHumanArmor.maxNerfGun = 0; + LightFemaleHumanArmor.maxNerfBallLauncher = 0; + LightMaleBiodermArmor.maxNerfGun = 0; + LightMaleBiodermArmor.maxNerfBallLauncher = 0; + + MediumMaleHumanArmor.maxNerfGun = 0; + MediumMaleHumanArmor.maxNerfBallLauncher = 0; + MediumFemaleHumanArmor.maxNerfGun = 0; + MediumFemaleHumanArmor.maxNerfBallLauncher = 0; + MediumMaleBiodermArmor.maxNerfGun = 0; + MediumMaleBiodermArmor.maxNerfBallLauncher = 0; + + HeavyMaleHumanArmor.maxNerfGun = 0; + HeavyMaleHumanArmor.maxNerfBallLauncher = 0; + HeavyFemaleHumanArmor.maxNerfGun = 0; + HeavyFemaleHumanArmor.maxNerfBallLauncher = 0; + HeavyMaleBiodermArmor.maxNerfGun = 0; + HeavyMaleBiodermArmor.maxNerfBallLauncher = 0; + + PureMaleHumanArmor.maxNerfGun = 0; + PureMaleHumanArmor.maxNerfBallLauncher = 0; + PureFemaleHumanArmor.maxNerfGun = 0; + PureFemaleHumanArmor.maxNerfBallLauncher = 0; + PureMaleBiodermArmor.maxNerfGun = 0; + PureMaleBiodermArmor.maxNerfBallLauncher = 0; + + %count = ClientGroup.getCount(); + for (%i=0;%i<%count;%i++) { + %client = ClientGroup.getObject(%i); + %player = %client.player; + if (isObject(%player)) { + %player.setInventory(NerfGun,0,true); + %client.setWeaponsHudItem(NerfGun,0,0); + %player.setInventory(NerfBallLauncher,0,true); + %player.setInventory(NerfBallLauncherAmmo,0,true); + %client.setWeaponsHudItem(NerfBallLauncher,0,0); + } + } +} diff --git a/scripts/pack.cs b/scripts/pack.cs new file mode 100644 index 0000000..2f252eb --- /dev/null +++ b/scripts/pack.cs @@ -0,0 +1,122 @@ +//---------------------------------------------------------------------------- + +datablock EffectProfile(TurretPackActivateEffect) +{ + effectname = "packs/generic_deploy"; + minDistance = 2.5; + maxDistance = 2.5; +}; + +datablock AudioProfile(TurretPackActivateSound) +{ + filename = "fx/packs/turret_place.wav"; + description = AudioClose3D; + preload = true; + effect = TurretPackActivateEffect; +}; + + +//---------------------------------------------------------------------------- + +function Pack::onCollision(%data, %obj, %col) +{ + // Don't pick up a new pack if you have a satchel charge deployed: + if ( %col.thrownChargeId > 0 ) + return; + + ItemData::onCollision(%data, %obj, %col); +} + +function Pack::onUse(%data,%obj) +{ + if (%obj.getMountedImage($BackpackSlot) != %data.image.getId()) + %obj.mountImage(%data.image,$BackpackSlot); + else + { + // Toggle the image trigger. + %obj.setImageTrigger($BackpackSlot, + !%obj.getImageTrigger($BackpackSlot)); + } +} + +function Pack::onInventory(%data,%obj,%amount) +{ + //only do this for players + if(%obj.getClassName() !$= "Player") + return; + + // Auto-mount the packs on players + if((%oldPack = %obj.getMountedImage($BackpackSlot)) != 0) + %obj.setInventory(%oldPack.item, 0); + if (%amount && %obj.getDatablock().className $= Armor) + { + // if you picked up another pack after you placed a satchel charge but + // before you detonated it, delete the charge + if(%obj.thrownChargeId > 0) + { + %obj.thrownChargeId.delete(); + %obj.thrownChargeId = 0; + } + %obj.mountImage(%data.image,$BackpackSlot); + %obj.client.setBackpackHudItem(%data.getName(), 1); + } + if(%amount == 0 ) + { + if ( %data.getName() $= "SatchelCharge" ) + %obj.client.setBackpackHudItem( "SatchelUnarmed", 1 ); + else + %obj.client.setBackpackHudItem(%data.getName(), 0); + } + ItemData::onInventory(%data,%obj,%amount); +} + +//---------------------------------------------------------------------------- + +// --- Upgrade packs +exec("scripts/packs/ammopack.cs"); +exec("scripts/packs/cloakingpack.cs"); +exec("scripts/packs/energypack.cs"); +exec("scripts/packs/repairpack.cs"); +exec("scripts/packs/shieldpack.cs"); +exec("scripts/packs/satchelCharge.cs"); +exec("scripts/packs/sensorjammerpack.cs"); + +exec("scripts/packs/largeInventory.cs"); +exec("scripts/packs/spine.cs"); +exec("scripts/packs/blastwall.cs"); +exec("scripts/packs/blastfloor.cs"); +exec("scripts/packs/blastwwall.cs"); +exec("scripts/packs/jumpad.cs"); +exec("scripts/packs/energizer.cs"); +exec("scripts/packs/mspine.cs"); +exec("scripts/packs/treepack.cs"); +exec("scripts/packs/cratepack.cs"); +exec("scripts/packs/decorationpack.cs"); +exec("scripts/packs/logoprojectorpack.cs"); +exec("scripts/packs/lightpack.cs"); +exec("scripts/packs/forcefieldpack.cs"); +exec("scripts/packs/gravityfieldpack.cs"); +exec("scripts/packs/telepadpack.cs"); +exec("scripts/packs/turretpack.cs"); +exec("scripts/packs/discturret.cs"); +exec("scripts/packs/laserturret.cs"); +exec("scripts/packs/missilerackturret.cs"); +exec("scripts/packs/mediumSensor.cs"); +exec("scripts/packs/largeSensor.cs"); +exec("scripts/packs/tripwire.cs"); +exec("scripts/packs/escapePodPack.cs"); +exec("scripts/packs/vehiclepad.cs"); +exec("scripts/packs/Effectpacks.cs"); +exec("scripts/packs/door.cs"); + +// --- Turret barrel packs +exec("scripts/packs/aabarrelpack.cs"); +exec("scripts/packs/missilebarrelpack.cs"); +exec("scripts/packs/mortarbarrelpack.cs"); +exec("scripts/packs/plasmabarrelpack.cs"); +exec("scripts/packs/ELFbarrelpack.cs"); + +// --- power +exec("scripts/packs/generator.cs"); +exec("scripts/packs/solarpanel.cs"); +exec("scripts/packs/switch.cs"); diff --git a/scripts/packs/AntiNuketurret.cs b/scripts/packs/AntiNuketurret.cs new file mode 100644 index 0000000..ccd8e9d --- /dev/null +++ b/scripts/packs/AntiNuketurret.cs @@ -0,0 +1,724 @@ +datablock TracerProjectileData(Mpm_Aexp1) { + className = "TracerProjectileData"; + emitterDelay = "-1"; + velInheritFactor = "0"; + directDamage = "0"; + hasDamageRadius = "0"; + indirectDamage = "0"; + damageRadius = "0"; + radiusDamageType = "0"; + kickBackStrength = "0"; + Explosion = "VehicleExplosion"; + hasLight = "0"; + lightRadius = "1"; + lightColor = "1.000000 1.000000 1.000000 1.000000"; + hasLightUnderwaterColor = "0"; + underWaterLightColor = "1.000000 1.000000 1.000000 1.000000"; + explodeOnWaterImpact = "0"; + depthTolerance = "5"; + bubbleEmitTime = "0.5"; + faceViewer = "0"; + scale = "1 1 1"; + dryVelocity = "0.1"; + wetVelocity = "0.1"; + fizzleTimeMS = "32"; + lifetimeMS = "32"; + explodeOnDeath = "1"; + reflectOnWaterImpactAngle = "0"; + deflectionOnWaterImpact = "0"; + fizzleUnderwaterMS = "-1"; + activateDelayMS = "-1"; + doDynamicClientHits = "0"; + tracerLength = "1"; + tracerMinPixels = "1"; + tracerAlpha = "0"; + tracerColor = "0.000000 0.000000 0.000000 0.000000"; + tracerTex[0] = "special/tracer00"; + tracerTex[1] = "special/tracercross"; + tracerWidth = "0.1"; + crossViewAng = "0.99"; + crossSize = "0.1"; + renderCross = "0"; + isFXUnit = "1"; +}; + +datablock TracerProjectileData(Mpm_Aexp2) : Mpm_Aexp1{ +Explosion = "TurretExplosion"; +}; + + + +//--------------------------------------------------------------------------- +// Explosions +//--------------------------------------------------------------------------- +datablock ExplosionData(Mpm_Anti_MissileExplosion) { + explosionShape = "effect_plasma_explosion.dts"; + playSpeed = 1.5; + soundProfile = GrenadeExplosionSound; + 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; +}; + +//-------------------------------------------------------------------------- +// Projectile +//-------------------------------------- +datablock SeekerProjectileData(Mpm_Anti_Missile) { + casingShapeName = "weapon_missile_casement.dts"; + projectileShapeName = "weapon_missile_projectile.dts"; + hasDamageRadius = true; + indirectDamage = 0.2; + damageRadius = 4.0; + radiusDamageType = $DamageType::MissileTurret; + kickBackStrength = 1000; + + explosion = "Mpm_Anti_MissileExplosion"; + splash = MissileSplash; + velInheritFactor = 0.2; // 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 = -1; + muzzleVelocity = 20.0; + maxVelocity = 20.0; + turningSpeed = 110.0; + acceleration = 0.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 TurretData(Mpm_Anti_TurretDeployed) : TurretDamageProfile { + className = DeployedTurret; + shapeFile = "turret_outdoor_deploy.dts"; + + rechargeRate = 0.15; + + mass = 1; + maxDamage = 0.80; + destroyedLevel = 0.80; + disabledLevel = 0.35; + + explosion = HandGrenadeExplosion; + expDmgRadius = 5.0; + expDamage = 0.5; + expImpulse = 500.0; + + repairRate = 0; + deployedObject = true; + + thetaMin = 0; + thetaMax = 145; + thetaNull = 90; + primaryAxis = zaxis; + + yawVariance = 30.0; // these will smooth out the elf tracking code. + pitchVariance = 30.0; // more or less just tolerances + + isShielded = true; + energyPerDamagePoint = 110; + maxEnergy = 80; + renderWhenDestroyed = true; + barrel = DeployableMpm_Anti_TurretBarrel; + heatSignature = 0.0; + + //canControl = true; + cmdCategory = "DTactical"; + cmdIcon = CMDTurretIcon; + cmdMiniIconName = "commander/MiniIcons/com_turret_grey"; + targetNameTag = 'Anti Missile'; + targetTypeTag = 'Turret'; + sensorData = Mpm_Anti_TurretSensor; + sensorRadius = Mpm_Anti_TurretSensor.detectRadius; + sensorColor = "191 0 226"; + + firstPersonOnly = true; + + debrisShapeName = "debris_generic_small.dts"; + debris = TurretDebrisSmall; + needsPower = true; +}; + +datablock TurretImageData(DeployableMpm_Anti_TurretBarrel) { + shapeFile = "stackable1s.dts"; + rotation = "-0.57735 0.57735 0.57735 120"; + offset = "0 -0.3 0"; + projectile = Mpm_Anti_Missile; + projectileType = SeekerProjectile; + + usesEnergy = true; + fireEnergy = 7.0; + minEnergy = 7.0 * 2; + + isSeeker = true; + seekRadius = 300; + maxSeekAngle = 30; + seekTime = 1.0; + minSeekHeat = 0.6; + emap = true; + minTargetingDistance = 15; + + // Turret parameters + activationMS = 250; + deactivateDelayMS = 500; + thinkTimeMS = 200; + degPerSecTheta = 50; + degPerSecPhi = 50; + attackRadius = 250; + + // State transitions + stateName[0] = "Activate"; + stateTransitionOnNotLoaded[0] = "Dead"; + stateTransitionOnLoaded[0] = "ActivateReady"; + + stateName[1] = "ActivateReady"; + stateSequence[1] = "Activate"; + stateSound[1] = IBLSwitchSound; + + stateTimeoutValue[1] = 1; + stateTransitionOnTimeout[1] = "Ready"; + stateTransitionOnNotLoaded[1] = "Deactivate"; + stateTransitionOnNoAmmo[1] = "NoAmmo"; + + stateName[2] = "Ready"; + stateTransitionOnNotLoaded[2] = "Deactivate"; + stateTransitionOnTriggerDown[2] = "Fire"; + stateTransitionOnNoAmmo[2] = "NoAmmo"; + + stateName[3] = "Fire"; + stateTransitionOnTimeout[3] = "Reload"; + stateTimeoutValue[3] = 0.3; + stateFire[3] = true; + stateShockwave[3] = true; + stateRecoil[3] = LightRecoil; + stateAllowImageChange[3] = false; + stateSequence[3] = "Fire"; + stateSound[3] = MissileRackTurretFireSound; + stateScript[3] = "onFire"; + + stateName[4] ="Reload"; + stateTimeoutValue[4] = 0.5; + stateAllowImageChange[4] = false; + stateSequence[4] = "Reload"; + stateTransitionOnTimeout[4] = "Ready"; + stateTransitionOnNotLoaded[4] = "Deactivate"; + stateTransitionOnNoAmmo[4] = "NoAmmo"; + + stateName[5] = "Deactivate"; + stateSequence[5] = "Activate"; + stateDirection[5] = false; + stateTimeoutValue[5] = 2; + stateTransitionOnLoaded[5] = "ActivateReady"; + stateTransitionOnTimeout[5] = "Dead"; + + stateName[6] = "Dead"; + stateTransitionOnLoaded[6] = "ActivateReady"; + + stateName[7] = "NoAmmo"; + stateTransitionOnAmmo[7] = "Reload"; + stateSequence[7] = "NoAmmo"; + + muzzleSlots = 12; + muzzleSlotOffset[0] = "0.65 0.5 0.4"; + muzzleSlotOffset[1] = "0.35 0.5 0.4"; + muzzleSlotOffset[2] = "0.15 0.5 0.4"; + muzzleSlotOffset[3] = "-0.15 0.5 0.4"; + muzzleSlotOffset[4] = "-0.35 0.5 0.4"; + muzzleSlotOffset[5] = "-0.65 0.5 0.4"; + muzzleSlotOffset[6] = "0.65 0.5 0.1"; + muzzleSlotOffset[7] = "0.35 0.5 0.1"; + muzzleSlotOffset[8] = "0.15 0.5 0.1"; + muzzleSlotOffset[9] = "-0.15 0.5 0.1"; + muzzleSlotOffset[10] = "-0.35 0.5 0.1"; + muzzleSlotOffset[11] = "-0.65 0.5 0.1"; +}; + +datablock TurretImageData(DeployableMpm_Anti_TurretBarrel1) { + shapeFile = "weapon_missile_projectile.dts"; + rotation = "1 0 0 0"; + offset = "-0.14 0.15 0.13"; + +}; + +datablock TurretImageData(DeployableMpm_Anti_TurretBarrel2) { + shapeFile = "weapon_missile_projectile.dts"; + rotation = "1 0 0 0"; + offset = "-0.14 0.15 -0.13"; +}; + +datablock TurretImageData(DeployableMpm_Anti_TurretBarrel3) { + shapeFile = "weapon_missile_projectile.dts"; + rotation = "1 0 0 0"; + offset = "-0.43 0.15 0.13"; +}; + +datablock TurretImageData(DeployableMpm_Anti_TurretBarrel4) { + shapeFile = "weapon_missile_projectile.dts"; + rotation = "1 0 0 0"; + offset = "-0.43 0.15 -0.13"; +}; + +function DeployableMpm_Anti_TurretBarrel::onMount(%this,%obj,%slot) { + %obj.currentMuzzleSlot = 0; + %obj.schedule(1000,"mountImage",DeployableMpm_Anti_TurretBarrel1,1,true); + %obj.schedule(1000,"mountImage",DeployableMpm_Anti_TurretBarrel2,2,true); + %obj.schedule(1000,"mountImage",DeployableMpm_Anti_TurretBarrel3,3,true); + %obj.schedule(1000,"mountImage",DeployableMpm_Anti_TurretBarrel4,4,true); +} + +// TODO - handle unmount + +datablock ShapeBaseImageData(TurretMpm_Anti_DeployableImage) { + mass = 1; + shapeFile = "pack_deploy_turreto.dts"; + item = TurretMpm_Anti_Deployable; + mountPoint = 1; + offset = "0 0 0"; + deployed = Mpm_Anti_TurretDeployed; + stateName[0] = "Idle"; + stateTransitionOnTriggerDown[0] = "Activate"; + + stateName[1] = "Activate"; + stateScript[1] = "onActivate"; + stateTransitionOnTriggerUp[1] = "Idle"; + + isLarge = true; + emap = true; + maxDepSlope = 360; + deploySound = TurretDeploySound; + minDeployDis = 0.5; + maxDeployDis = 5.0; +}; + +datablock ItemData(TurretMpm_Anti_Deployable) { + className = Pack; + catagory = "Deployables"; + shapeFile = "pack_deploy_turreti.dts"; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 1; + rotate = false; + image = TurretMpm_Anti_DeployableImage; + pickUpName = "an anti missile turret pack"; + emap = true; +}; + +//-------------------------------------------------------------------------- +// Functions +//-------------------------------------- + +function TurretMpm_Anti_DeployableImage::TestNoTerrainFound(%item) { + // created to prevent console errors +} + +function TurretMpm_Anti_DeployableImage::TestNoInteriorFound(%item) { + // created to prevent console errors +} + +function TurretMpm_Anti_Deployable::onPickup(%this, %obj, %shape, %amount) { + //created to prevent console errors +} + + +function TurretMpm_Anti_DeployableImage::onDeploy(%item, %plyr, %slot) { + %className = "Turret"; + if (IsObject(%item.surface)) + if (%item.surface.getDatablock().getName() $= Mpm_Anti_TurretDeployed) + { + for (%i=1;%i<5;%i++) + { + if (!%item.surface.getMountedImage(%i)) + { + %item.surface.schedule(%i*100,"mountImage","DeployableMpm_Anti_TurretBarrel"@ %i,%i,true); + %item.surface.schedule(%i*100,"play3d",NerfGunDryFireSound); + %c++; + } + if (%c) + bottomPrint( %plyr.client, "Reloaded anti-mpm Turret with" SPC %c SPC "Missiles", 5,1); + } + return ""; + } + %playerVector = vectorNormalize(getWord(%plyr.getEyeVector(),1) SPC -1 * getWord(%plyr.getEyeVector(),0) SPC "0"); + + if (vAbs(floorVec(%item.surfaceNrm,100)) $= "0 0 1") + %item.surfaceNrm2 = %playerVector; + else + %item.surfaceNrm2 = vectorNormalize(vectorCross(%item.surfaceNrm,"0 0 1")); + + %rot = fullRot(%item.surfaceNrm,%item.surfaceNrm2); + + %deplObj = new (%className)() { + dataBlock = %item.deployed; + }; + + if (%plyr.packSet == 1) + %deplObj.isSeeker = true; + + // set orientation + %deplObj.setTransform(%item.surfacePt SPC %rot); + + // set team, owner, and handle + %deplObj.team = %plyr.client.Team; + %deplObj.setOwner(%plyr); + + // set power frequency + %deplObj.powerFreq = %plyr.powerFreq; + + // set the sensor group if it needs one + if (%deplObj.getTarget() != -1) + setTargetSensorGroup(%deplObj.getTarget(), %plyr.client.team); + + // place the deployable in the MissionCleanup/Deployables group (AI reasons) + addToDeployGroup(%deplObj); + + //let the AI know as well... + AIDeployObject(%plyr.client, %deplObj); + + // play the deploy sound + serverPlay3D(%item.deploySound, %deplObj.getTransform()); + + // increment the team count for this deployed object + $TeamDeployedCount[%plyr.team, %item.item]++; + + %deplObj.deploy(); + + // Power object + checkPowerObject(%deplObj); + + addDSurface(%item.surface,%deplObj); + + // take the deployable off the player's back and out of inventory + %plyr.unmountImage(%slot); + %plyr.decInventory(%item.item, 1); + bottomPrint( %plyr.client, "Deployed anti-mpm Turret with 4 missiles ammo.\n deploy another anti-mpm turret ontop to resuply.", 5,2); + return %deplObj; +} + +function Mpm_Anti_TurretDeployed::onDestroyed(%this, %obj, %prevState) { + if (%obj.isRemoved) + return; + if ($Host::InvincibleDeployables != 1 || %obj.damageFailedDecon) { + %obj.isRemoved = true; + $TeamDeployedCount[%obj.team, TurretMpm_Anti_Deployable]--; + remDSurface(%obj); + %obj.schedule(500, delete); + } + Parent::onDestroyed(%this, %obj, %prevState); +} + +function DeployableMpm_Anti_TurretBarrel::onFire(%data,%obj,%slot) { + %targetObj = %obj.getTargetObject(); + if (%targetObj) { + if (!%obj.getDataBlock().hasLOS(%obj,%slot,%targetObj) && %obj.aquireTime + 2000 < getSimTime()) { + %obj.clearTarget(); + return; + } + if (%obj.aquireTime + 10000 + getRandom(0,1000) < getSimTime()) { + %obj.clearTarget(); + return; + } + } + + %p = Parent::onFire(%data,%obj,%slot); + serverPlay3D(MissileRackTurretFireSound2,%obj.getTransform()); + + if (%obj.isSeeker) { + if (%obj.getControllingClient()) + // a player is controlling the turret + %target = %obj.getLockedTarget(); + else + // The ai is controlling the turret + %target = %obj.getTargetObject(); + + if(%target) + %p.setObjectTarget(%target); + else if(%obj.isLocked()) + %p.setPositionTarget(%obj.getLockedPosition()); + else + %p.setNoTarget(); // set as unguided. Only happens when itchy trigger can't wait for lock tone. + %obj.setEnergyLevel(%obj.getEnergyLevel() - (%data.fireEnergy)); + } +} + +function Mpm_Anti_TurretDeployed::hasLOS(%data,%obj,%slot,%targetObj) { + %start = %obj.getMuzzlePoint(%slot); + %end = %targetObj.getWorldBoxCenter(); + %res = containerRayCast(%start,%end,-1,%obj); + return firstWord(%res) == %targetObj; +} + +function TurretMpm_Anti_DeployableImage::onMount(%data, %obj, %node) { + %obj.hasMpm_Anti= true; // set for Mpm_Anti_check + %obj.packSet = 0; + displayPowerFreq(%obj); +} + +function TurretMpm_Anti_DeployableImage::onUnmount(%data, %obj, %node) { + %obj.hasMpm_Anti= ""; + %obj.packSet = 0; +} + + +function Mpm_Anti_TurretDeployed::selectTarget(%this, %turret) +{ +%turretTarg = %turret.getTarget(); + if(%turretTarg == -1) + return; +if (Isobject(%turret.aimtarget)) + { + %turret.setTargetObject(%turret.aimtarget); + } +%target = %turret.get_ampm_target(); +if (Isobject(%target)) + { + %turret.Lock_ampm_target(%target); + } +} + +function GameBase::Get_ampm_target(%obj) +{ +%location = %obj.getTransform(); +if (!Isobject(mpm_missiles)) + return ""; +if (!mpm_missiles.getCount()) + return ""; + +%tmissile = ""; +for( %c = 0; %c < mpm_missiles.getCount(); %c++ ) + { + %missile = mpm_missiles.getObject(%c); + if (%missile.load.Hazard(%missile,%obj,200) && !Isobject(%obj.tagged[%missile]) && !%missile.tagged && (!isObject(%missile.tracking) || %obj == %missile.tracking)) + { + %pos = pos(%missile); + %dist = vectorDist(%location,%pos); + if (!%dis || %dist < %dis) + { + %tmissile = %missile; + %dis = %dist; + } + } + } +return %tmissile SPC %dist; +} + +function GameBase::Lock_ampm_target(%obj,%target) +{ +if (IsObject(%target)) //Is the target still there? + { + %predict= %target.predict(); + %loc = getWords(%predict,0,2); + %speed = getWords(%predict,3,5); + %pos = %obj.getTransform(); + %dist = VectorDist(%pos,%loc); + //%dir = VectorSub(%pos,%loc); + //%gendir = VectorDot(VectorNormalize(%dir),VectorNormalize(%speed)); + %time = 15;//Limit(%dist/20+5-10,5,50); //%target.radiustime(%pos,100); + if (%time > 5 && getSimTime()+ %time*1000 < %target.dietime) //Can we get to the target in time? + { + %loc = getWords(%target.predict((%time)*1000),0,2); + %dist = VectorDist(%pos,%loc); + %ttime = %dist / 20; //travel time + %ltime = %time - %ttime; //launch time + %atime = %ltime - 3; //activate time + if (%dist > 10 && %dist < 500 && %atime > 0) //Will it within our limits? + { + %res = containerRayCast(%obj.getTransform(),%loc, -1,%obj); + if (!%res) //Can we hit it from here? + { + if ((%obj.atime-getSimTime())/1000 > %atime || (%obj.ltime-getSimTime())/1000 < 0) //Is it a better option? + { + Cancel(%obj.activate); + Cancel(%obj.launch); + %obj.needtime = getSimTime()+(%time*1000); + %obj.atime = getSimTime()+(%atime*1000); + %obj.ltime = getSimTime()+(%ltime*1000); + %obj.set_ampm_target(%loc); + %target.tracking = %obj; + %obj.activate = %obj.schedule(%atime*1000,"set_ampm_target",%target,%loc); + %obj.launch = %obj.schedule(%ltime*1000,"fire_ampm_now"); + } + } + } + } + } +} + +function GameBase::set_ampm_target(%obj,%target,%location) +{ +if (!Isobject(%obj.aimtarget)) + { + //SIGN + %sign = new StaticShape(){ + dataBlock = MpmTurretTarg; + }; + %sign.team = 3; + %sign.setHeat(1); + setTargetSensorGroup(%sign.getTarget(),3); + %sign.owner = %obj; + %obj.aimtarget = %sign; + } +if (%location $= "" || !Isobject(%target) || IsObject(%obj.tagged[%target]) || !%obj.get_ampm_missile()) + { + Cancel(%obj.launch); + %pos = VectorAdd(%obj.getMuzzlePoint(0),realvec(%obj,"0 10 0")); + %obj.aimtarget.setTransform(%pos SPC "1 0 0 0"); + %obj.canfire = 0; + } +else + { + %obj.aimtarget.setTransform(%location SPC "1 0 0 0"); + %obj.target = %target; + %obj.canfire = 1; + } +} + +function GameBase::Fire_ampm_now(%obj) +{ + +%target = %obj.target; +if (IsObject(%target) && %obj.canfire && IsObject(%obj.aimtarget)) + { + %slot = %obj.get_ampm_missile(); + %from = %obj.getMuzzlePoint(%slot); + %pos = %obj.aimtarget.getTransform(); + %vec = VectorSub(%pos,%from); + %tdir = VectorNormalize(VectorSub(%pos,%from)); + %tvec = "0 1 0"; + %rot = %obj.getSlotRotation(0); + %dir = validateVal(MatrixMulVector("0 0 0" SPC %rot ,%tvec)); + %diff = vectorDot(%tdir,%dir); + %time = (%obj.needtime-getSimTime())/1000; + %speed = (VectorLen(%vec)/%time)/MpmMissile3.muzzleVelocity; + + if (%diff > 0.9 && %slot) + { + %p1 = new SeekerProjectile() + { + datablock = Mpm_B_MIS2; + initialDirection = VectorScale(%tdir,%speed); + initialPosition = %from; + }; + %p1.schedule(%time*1000+500,"delete"); + schedule(%time*1000,0,"range",%target,%p1); + %p1.getDatablock().schedule(%time*1000,"onExplode",%p1,%pos, 1); + %obj.tagged[%target] = %p1; + %target.tagged = 1; + %obj.set_ampm_target(0); + %obj.unMountImage(%slot); + } + } +} + + + +function range(%p1,%p2) +{ +if (IsObject(%p1) && IsObject(%p2)) +{ +%dist = VectorDist(%p1.getTransform(),%p2.getTransform()); +PlayExplosion(%p1.getTransform(),Mpm_Aexp1); + +if (%dist < 10) + { + //createLifeEmitter(%p1.getTransform(), MpmJetEmitter3, 5000,"1 0 0 0"); + PlayExplosion(%p1.getTransform(),Mpm_Aexp2); + %p1.load.InterCept(%p1); + } +} +} + +function GameBase::get_ampm_missile(%obj) +{ +for (%i=1;%i<5; %i++) + { + if (%obj.getMountedImage(%i)!=0) + return %i; + } +return ""; +} + +//Not used.. ha +function inrange(%p,%loc,%range) +{ +if (!Isobject(%p)) + return ""; +%c = VectorSub(%p.getTransform(),%loc); +%speed = GetWords(%p.predict(),3,5); +%r = VectorNormalize(%speed); +%v = VectorLen(%speed); +%a = %p.getDatablock().Acceleration; + +if (%a != 0) + { + %root1 = mPow(VectorDot(%r,%c),2) * VectorDot(%r,%r) * (mPow(%g,2)-VectorDot(%c,%c)); + if (%root1 < 0) //Will never be in range. + return ""; + %root2 = VectorDot(%r,%r)*(VectorDot(%r,%r)*mPow(%v,2)-2*%a*(VectorDot(%r,%c)+mSqrt(%root))); + if (%root2 < 0) //Will never be in range. + return ""; + %time = (-1*%v + mSqrt(%root2)/VectorDot(%r,%r))/%a; + if (%time < 0) //'was'in range. + return ""; + return %time; //Note this is seconds not ms. + } +else + { + %root = mPow(%v)*(4*VectorDot(%r,%c) - 4*VectorDot(%r,%r)*(VectorDot(%c,%c)-mPow(%g,2))); + if (%root < 0) //Will never be in range. + return ""; + %time = (-2*%v*VectorDot(%r,%c) + mSqrt(%root)) / (2*VectorDot(%r,%r) * mPow(%v,2)); + if (%time < 0) //'was'in range. + return ""; + return %time; //Note this is seconds not ms. + } +} + diff --git a/scripts/packs/Effectpacks.cs b/scripts/packs/Effectpacks.cs new file mode 100644 index 0000000..cb1df64 --- /dev/null +++ b/scripts/packs/Effectpacks.cs @@ -0,0 +1,1806 @@ +function Gamebase::addTofxGroup(%obj,%set) +{ +if (!isObject(%obj)) + return ""; + if (!isObject(fxGroup)) + { + %main = new SimGroup("fxGroup"); + MissionCleanup.add(%main); + %em = new Simgroup("fx_emitters"); + %au = new Simgroup("fx_audio"); + %pa = new Simgroup("fx_packs"); + %main.add(%em); + %main.add(%au); + %main.add(%pa); + } +if (IsObject(%obj)) + { + if (%set == 1) + fx_audio.add(%obj); + else if (%set == 2) + fx_packs.add(%obj); + else + fx_emitters.add(%obj); + } +} + + + +/////////EMITTER PACK////////// + +//Example of using expert setting to select pack setting mode. +//Note uses custom (plugin) packsettings mode + +//Format = "%modes %lines %name" +//%modes gives the highest mode like the old settings +//%lines gives the amount of words in the settings which are the name of the mode +// -1 gives the entire content of the mode +// 2 would give the first 3 words of the mode +//%name gives the name of the pack as in %name "set to" %modename + +$expertSettings[EmitterDepImage] = "3 -1 Emitter Pack:[Options]"; + +$expertSetting[EmitterDepImage,0] = "Select Emitter"; +$expertSetting[EmitterDepImage,1] = "Select Emitter selection mode"; +$expertSetting[EmitterDepImage,2] = "Select Power logic"; +$expertSetting[EmitterDepImage,3] = "Select Cloak logic"; + +//These are my personal browse of the first few datablocks. +$packSettings[EmitterDepImage] = "13 1 Emitter Pack:[Emitter]"; +$packSetting[EmitterDepImage,0] = "Small Steam ReverseEmitter"; +$packSetting[EmitterDepImage,1] = "Small Bubbles GrenadeBubbleEmitter"; +$packSetting[EmitterDepImage,2] = "Large Foam VehicleFoamEmitter"; +$packSetting[EmitterDepImage,3] = "Small Fire PlasmaExplosionEmitter"; +$packSetting[EmitterDepImage,4] = "Plasma Stream PlasmaRifleEmitter"; +$packSetting[EmitterDepImage,5] = "Large Bubbles DiscExplosionBubbleEmitter"; +$packSetting[EmitterDepImage,6] = "Dark Smoke GDebrisSmokeEmitter"; +$packSetting[EmitterDepImage,7] = "Small Smoke GrenadeSmokeEmitter"; +$packSetting[EmitterDepImage,8] = "Small Spark ELFSparksEmitter"; +$packSetting[EmitterDepImage,9] = "Green Smoke MortarSmokeEmitter"; +$packSetting[EmitterDepImage,10] = "Fire Stream MissileFireEmitter"; +$packSetting[EmitterDepImage,11] = "Water Stream WaterStreamEmitter"; +$packSetting[EmitterDepImage,12] = "min hole LoadingE2"; +$packSetting[EmitterDepImage,13] = "wisps flair LoadingE"; + +//Note how the extra %id defines the nesting of the modes. +//While previous settings could also include %id=0 I chose not to use that +//since nesting isn't directly compatible with the unified code. +//Using non nesting format for the previous allows me to use the unified code +//for that setting. + +$packSettings[EmitterDepImage,1] = "1 -1 Emitter Pack: [Selection mode]"; +$packSetting[EmitterDepImage,0,1] = "Small selection"; +$packSetting[EmitterDepImage,1,1] = "Sellect from datablocks"; + +$packSettings[EmitterDepImage,2] = "3 -1 Emitter Pack: [Power Logic]"; +$packSetting[EmitterDepImage,0,2] = "Always on"; +$packSetting[EmitterDepImage,1,2] = "On when powered"; +$packSetting[EmitterDepImage,2,2] = "Off when powered"; +$packSetting[EmitterDepImage,3,2] = "5 sec on when power change"; + +$packSettings[EmitterDepImage,3] = "1 -1 Emitter Pack: [Cloak Logic]"; +$packSetting[EmitterDepImage,0,3] = "Always Vissible"; +$packSetting[EmitterDepImage,1,3] = "Cloaked when emitting"; +//Removed +$packSetting[EmitterDepImage,2,3] = "Cloaked when not emtting"; +$packSetting[EmitterDepImage,3,3] = "Always Cloaked"; + + +datablock ParticleData( WaterStreamParticle ) +{ + dragCoeffiecient = 0.0; + gravityCoefficient = 1.0; + inheritedVelFactor = 0.0; + + lifetimeMS = 25000; + lifetimeVarianceMS = 100; + + textureName = "special/bubbles"; + + useInvAlpha = false; + + spinRandomMin = -360.0; + spinRandomMax = 360.0; + + colors[0] = "0.4 0.4 0.8 1.0"; + colors[1] = "0.3 0.3 0.8 0.1"; + colors[2] = "0.0 0.0 0.8 0.0"; + sizes[0] = 0.4; + sizes[1] = 0.5; + sizes[2] = 0.7; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; +}; + +datablock ParticleEmitterData( WaterStreamEmitter ) +{ + ejectionPeriodMS = 5; + periodVarianceMS = 1; + + ejectionVelocity = 30.0; // A little oomph at the back end + velocityVariance = 1.0; + + thetaMin = 0.0; + thetaMax = 1.0; + + + orientParticles = False; + orientOnVelocity = False; + + particles = "WaterStreamParticle"; +}; + + +datablock StaticShapeData(EmitterDep) : DeployedCrate +{ + shapeFile = "stackable4l.dts"; + needsPower = true; +}; + +datablock ShapeBaseImageData(EmitterDepImage) { + mass = 1; + emap = true; + shapeFile = "stackable4l.dts"; + item = EmitterDepPack; + mountPoint = 1; + offset = "0 -0.18 -0.5"; + deployed = EmitterDepImage; + heatSignature = 0; + + stateName[0] = "Idle"; + stateTransitionOnTriggerDown[0] = "Activate"; + + stateName[1] = "Activate"; + stateScript[1] = "onActivate"; + stateTransitionOnTriggerUp[1] = "Idle"; + + isLarge = true; + maxDepSlope = 360; + deploySound = ItemPickupSound; + + minDeployDis = 0.5; + maxDeployDis = 50.0; +}; + +datablock ItemData(EmitterDepPack) { + className = Pack; + catagory = "Deployables"; + shapeFile = "stackable4l.dts"; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 1; + rotate = true; + image = "EmitterDepImage"; + pickUpName = "an Emitter pack"; + heatSignature = 0; + emap = true; + }; + +function EmitterDepPack::onPickup(%this, %obj, %shape, %amount) { + // created to prevent console errors +} + +function EmitterDep::gainPower(%data, %obj) +{ +if (%obj.pLogic==0) + EmitterDepSet(%obj,1); +if (%obj.pLogic==1) + EmitterDepSet(%obj,1); +if (%obj.pLogic==2) + EmitterDepSet(%obj,0); +if (%obj.pLogic==3) + { + EmitterDepSet(%obj,1); + schedule(5000,%obj,"EmitterDepSet",%obj,0); + } +} + +function EmitterDep::losePower(%data, %obj) +{ +if (%obj.pLogic==0) + EmitterDepSet(%obj,1); +if (%obj.pLogic==1) + EmitterDepSet(%obj,0); +if (%obj.pLogic==2) + EmitterDepSet(%obj,1); +if (%obj.pLogic==3) + { + EmitterDepSet(%obj,1); + schedule(5000,%obj,"EmitterDepSet",%obj,0); + } + +} + + + +function EmitterDepImage::onDeploy(%item, %plyr, %slot) { + + %playerVector = vectorNormalize(-1 * getWord(%plyr.getEyeVector(),1) SPC getWord(%plyr.getEyeVector(),0) SPC "0"); + %item.surfaceNrm2 = %playerVector; + %rot = fullRot(%item.surfaceNrm,%item.surfaceNrm2); + + %deplObj = new StaticShape() + { + dataBlock = "EmitterDep"; + scale = "0.5 0.5 0.1"; + }; + + // set orientation + %deplObj.setTransform(%item.surfacePt SPC %rot); + + // set the recharge rate right away + if (%deplObj.getDatablock().rechargeRate) + %deplObj.setRechargeRate(%deplObj.getDatablock().rechargeRate); + + // set team, owner, and handle + %deplObj.team = %plyr.client.Team; + %deplObj.setOwner(%plyr); + if (%plyr.packset == -1) + %deplObj.Emitterblock = datablockGroup.getObject(%plyr.packset[0]); + else if (%plyr.packset[0] $= "") + %deplObj.Emitterblock = GetWord($packSetting[EmitterDepImage,0],2); + else + %deplObj.EmitterBlock = %plyr.packset[0]; + + %deplObj.pLogic = %plyr.packset[2]; + %deplObj.cLogic = %plyr.packset[3]; + + // place the deployable in the MissionCleanup/Deployables group (AI reasons) + addToDeployGroup(%deplObj); + + //let the AI know as well... + AIDeployObject(%plyr.client, %deplObj); + + // play the deploy sound + serverPlay3D(%item.deploySound, %deplObj.getTransform()); + + // increment the team count for this deployed object + $TeamDeployedCount[%plyr.team, %item.item]++; + + addDSurface(%item.surface,%deplObj); + %deplObj.powerFreq = %plyr.powerFreq; + checkPowerObject(%deplObj); + if (!%plyr.client.isAdmin) + { + %plyr.unmountImage(%slot); + %plyr.decInventory(%item.item, 1); + } + + + return %deplObj; +} + +function EmitterDep::onDestroyed(%this,%obj,%prevState) { + if (%obj.isRemoved) + return; + %obj.isRemoved = true; + EmitterDepSet(%obj,0); + Parent::onDestroyed(%this,%obj,%prevState); + $TeamDeployedCount[%obj.team, EmitterDepPack]--; + remDSurface(%obj); + %obj.schedule(500, "delete"); +} + +function EmitterDepImage::onMount(%data, %obj, %node) { + displayPowerFreq(%obj); + %obj.hasEmpack = true; // not needed anymore + %obj.packSet = 0; + %obj.packSet[0] = 0; + %obj.packSet[1] = 0; + %obj.packSet[2] = 0; + %obj.packSet[3] = 0; +} + +function EmitterDepImage::onUnmount(%data, %obj, %node) { + %obj.hasEmpack = ""; // not needed anymore + %obj.packSet = 0; + %obj.packSet[0] = 0; + %obj.packSet[1] = 0; + %obj.packSet[2] = 0; + %obj.packSet[3] = 0; +} + +function EmitterDepSet(%obj,%set) +{ +if (ISobject(%obj)) + { + if (!%set && IsObject(%obj.emitter)) + { + %obj.emitter.delete(); + if (%obj.cLogic == 2 || %obj.cLogic == 3) + %obj.startfade(0,0,1); + else if (%obj.cLogic == 1) + %obj.startfade(0,0,0); + } + if (%set && !ISobject(%obj.emitter)) + { + %obj.emitter = CreateEmitter("0 0 0",%obj.emitterblock); + %obj.emitter.addTofxGroup(); + %obj.emitter.setTransform(%obj.getTransform()); + if (%obj.cLogic == 1 || %obj.cLogic == 3) + %obj.startfade(0,0,1); + else if (%obj.cLogic == 2) + %obj.startfade(0,0,0); + } + } +} + +//Example of nested setting modes with plugin capability. +//All but the first part of packssets are fully global defined. +//Expert mode and the very first packset refer back to the unified code. + +function EmitterDepImage::ChangeMode(%data,%plyr,%val,%level) +{ +if (%level == 0) + { + //Selecting emitter + if (!%plyr.expertSet) + { + if (!%plyr.packset[1]) + { + Parent::ChangeMode(%data,%plyr,%val,%level); + %plyr.packset[0] = GetWord($packSetting[EmitterDepImage,%plyr.packset],2); + } + else + { + %plyr.packset = -1; + %plyr.packset[0] = nextEmitter(%plyr.packset[0]+%val,%val); + %name = datablockGroup.getObject(%plyr.packset[0]).GetName(); + bottomPrint(%plyr.client,"Emitter pack set to emit:"SPC %name,2,1); + } + } + //Selecting selection mode/PowerLogic/CloakLogic + else if (%plyr.expertSet > 0) + { + %set = %plyr.expertSet; + %image = %data.getName(); + %settings = $packSettings[%image,%set]; + + %plyr.packSet[%set] = %plyr.packSet[%set] + %val; + if (%plyr.packSet[%set] > getWord(%settings,0)) + %plyr.packSet[%set] = 0; + if (%plyr.packSet[%set] < 0) + %plyr.packSet[%set] = getWord(%settings,0); + + %packname = GetWords(%settings,2,getWordCount(%settings)); + %curset = $PackSetting[%image,%plyr.packSet[%set],%set]; + if (getWord(%settings,1) == -1) + %line = GetWords(%curset,0,getWordCount(%curset)); + else + %line = GetWords(%curset,0,getWord(%settings,1)); + bottomPrint(%plyr.client,%packname SPC "set to"SPC %line,2,1); + } + } +else + { + Parent::ChangeMode(%data,%plyr,%val,%level); + } +} + +//Custion function to browse through all datablocks for emitter types. +//Allthought the cyclign takes forever and there can't be 1 proper name for each emitter +//It allows the player to fully utilize t2's content. + +function nextEmitter(%start,%dir) +{ +if (%dir == 1) + { + for(%i = %start; %i < DatablockGroup.getCount() ; %i++) + { + if (datablockGroup.getObject(%i).particles !$= "") + { + return %i; + } + } + return nextEmitter(0,1); + } +else + { + for(%i = %start; %i > 0; %i--) + { + if (datablockGroup.getObject(%i).particles !$= "") + { + return %i; + } + } + return nextEmitter(DatablockGroup.getCount(),-1); + } +} + +/////////Audio PACK////////// +//This is a total copy/past from the emitter deployable + + +$expertSettings[AudioDepImage] = "3 -1 Emitter Pack:[Options]"; +$expertSetting[AudioDepImage,0] = "Select Emitter"; +$expertSetting[AudioDepImage,1] = "Select Emitter selection mode"; +$expertSetting[AudioDepImage,2] = "Select Power logic"; +$expertSetting[AudioDepImage,3] = "Select Loop logic"; + +//Some I made myself +$packSettings[AudioDepImage] = "16 1 Emitter Pack:[Emitter]"; +$packSetting[AudioDepImage,0] = "Jeti howl1 fx/environment/yeti_howl1.wav"; +$packSetting[AudioDepImage,1] = "Jeti howl2 fx/environment/yeti_howl2.wav"; +$packSetting[AudioDepImage,2] = "Jeti growl fx/environment/growl1.wav"; +$packSetting[AudioDepImage,3] = "Frog sounds fx/environment/frog2.wav"; +$packSetting[AudioDepImage,4] = "fly swarm fx/environment/fly_swarm.wav"; +$packSetting[AudioDepImage,5] = "Bird sound1 fx/environment/bird_echo4.wav"; +$packSetting[AudioDepImage,6] = "Bird sound2 fx/environment/bird_echo5.wav"; +$packSetting[AudioDepImage,7] = "Ocean waves fx/environment/Oceanwaves.wav"; +$packSetting[AudioDepImage,8] = "River stream fx/environment/River2.wav"; +$packSetting[AudioDepImage,9] = "Cha ching fx/misc/bounty_bonus.wav"; +$packSetting[AudioDepImage,10] = "Mario party fx/Bonuses/mario-6notes.wav"; +$packSetting[AudioDepImage,11] = "Slick music fx/Bonuses/med-level4-slick.wav"; +$packSetting[AudioDepImage,12] = "test music t2Intro.wav"; +$packSetting[AudioDepImage,13] = "Tessios Heist-swing fx/bonuses/horz_straipass2_heist.wav"; +$packSetting[AudioDepImage,14] = "Swami swashi fx/bonuses/low-level2-spitting.wav"; +$packSetting[AudioDepImage,15] = "Smoking something fx/bonuses/med-level1-modest.wav"; +$packSetting[AudioDepImage,16] = "Swami swashi2 fx/bonuses/med-level3-shining.wav"; + +$packSettings[AudioDepImage,1] = "1 -1 Emitter Pack: [Selection mode]"; +$packSetting[AudioDepImage,0,1] = "Small selection"; +$packSetting[AudioDepImage,1,1] = "Sellect from datablocks"; + +$packSettings[AudioDepImage,2] = "3 -1 Emitter Pack: [Power Logic]"; +$packSetting[AudioDepImage,0,2] = "Always on"; +$packSetting[AudioDepImage,1,2] = "On when powered"; +$packSetting[AudioDepImage,2,2] = "Off when powered"; +$packSetting[AudioDepImage,3,2] = "5 sec on when power change"; + +//Cloak logic was left out as it won't help the global image. +//And it will only worsen spam. + +$packSettings[AudioDepImage,3] = "1 -1 Emitter Pack: [Loop Logic]"; +$packSetting[AudioDepImage,0,3] = "Use standard"; +$packSetting[AudioDepImage,1,3] = "Always loop"; + + + +datablock StaticShapeData(AudioDep) : DeployedCrate +{ + shapeFile = "stackable2l.dts"; + needsPower = true; +}; + +datablock ShapeBaseImageData(AudioDepImage) { + mass = 1; + emap = true; + shapeFile = "stackable3s.dts"; + item = AudioDepPack; + mountPoint = 1; + offset = "0.5 -0.5 0"; + rotation = "0 1 0 90"; + deployed = AudioDepImage; + heatSignature = 0; + + stateName[0] = "Idle"; + stateTransitionOnTriggerDown[0] = "Activate"; + + stateName[1] = "Activate"; + stateScript[1] = "onActivate"; + stateTransitionOnTriggerUp[1] = "Idle"; + + isLarge = true; + maxDepSlope = 360; + deploySound = ItemPickupSound; + + minDeployDis = 0.5; + maxDeployDis = 50.0; +}; + +datablock ItemData(AudioDepPack) { + className = Pack; + catagory = "Deployables"; + shapeFile = "stackable3s.dts"; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 1; + rotate = true; + image = "AudioDepImage"; + pickUpName = "an Sound pack"; + heatSignature = 0; + emap = true; + }; + + +function AudioDepPack::onPickup(%this, %obj, %shape, %amount) { + // created to prevent console errors +} + +function AudioDep::gainPower(%data, %obj) +{ +if (%obj.pLogic==0) + AudioDepSet(%obj,1); +if (%obj.pLogic==1) + AudioDepSet(%obj,1); +if (%obj.pLogic==2) + AudioDepSet(%obj,0); +if (%obj.pLogic==3) + { + AudioDepSet(%obj,1); + schedule(5000,%obj,"AudioDepSet",%obj,0); + } +} + +function AudioDep::losePower(%data, %obj) +{ +if (%obj.pLogic==0) + AudioDepSet(%obj,1); +if (%obj.pLogic==1) + AudioDepSet(%obj,0); +if (%obj.pLogic==2) + AudioDepSet(%obj,1); +if (%obj.pLogic==3) + { + AudioDepSet(%obj,1); + schedule(5000,%obj,"AudioDepSet",%obj,0); + } + +} + + + +function AudioDepImage::onDeploy(%item, %plyr, %slot) { + + %playerVector = vectorNormalize(-1 * getWord(%plyr.getEyeVector(),1) SPC getWord(%plyr.getEyeVector(),0) SPC "0"); + %item.surfaceNrm2 = %playerVector; + %rot = fullRot(%item.surfaceNrm,%item.surfaceNrm2); + + %deplObj = new StaticShape() + { + dataBlock = "AudioDep"; + scale = "0.4 0.4 0.1"; + }; + + // set orientation + %deplObj.setTransform(%item.surfacePt SPC %rot); + + // set the recharge rate right away + if (%deplObj.getDatablock().rechargeRate) + %deplObj.setRechargeRate(%deplObj.getDatablock().rechargeRate); + + // set team, owner, and handle + %deplObj.team = %plyr.client.Team; + %deplObj.setOwner(%plyr); + if (%plyr.packset == -1) + %deplObj.Audioblock = datablockGroup.getObject(%plyr.packset[0]); + else if (%plyr.packset[0] !$= "") + %deplObj.AudioBlock = %plyr.packset[0]; + else + %deplObj.Audioblock = GetWord($packSetting[AudioDepImage,0],2); + + + %deplObj.pLogic = %plyr.packset[2]; + %deplObj.lLogic = %plyr.packset[3]; + + // place the deployable in the MissionCleanup/Deployables group (AI reasons) + addToDeployGroup(%deplObj); + + //let the AI know as well... + AIDeployObject(%plyr.client, %deplObj); + + // play the deploy sound + serverPlay3D(%item.deploySound, %deplObj.getTransform()); + + // increment the team count for this deployed object + $TeamDeployedCount[%plyr.team, %item.item]++; + + addDSurface(%item.surface,%deplObj); + %deplObj.powerFreq = %plyr.powerFreq; + checkPowerObject(%deplObj); + + if (!%plyr.client.isAdmin) + { + %plyr.unmountImage(%slot); + %plyr.decInventory(%item.item, 1); + } + return %deplObj; +} + +function AudioDep::onDestroyed(%this,%obj,%prevState) { + if (%obj.isRemoved) + return; + %obj.isRemoved = true; + AudioDepSet(%obj,0); + Parent::onDestroyed(%this,%obj,%prevState); + $TeamDeployedCount[%obj.team, AudioDepPack]--; + remDSurface(%obj); + %obj.schedule(500, "delete"); +} + +function AudioDepImage::onMount(%data, %obj, %node) { + displayPowerFreq(%obj); + %obj.hasAupack = true; // not needed + %obj.packSet = 0; + %obj.packSet[0] = ""; + %obj.packSet[1] = 0; + %obj.packSet[2] = 0; + %obj.packSet[3] = 0; +} + +function AudioDepImage::onUnmount(%data, %obj, %node) { + %obj.hasAupack = ""; + %obj.packSet = 0; + %obj.packSet[0] = ""; + %obj.packSet[1] = 0; + %obj.packSet[2] = 0; + %obj.packSet[3] = 0; +} + +//We will keep calling the audio emitter %obj.emitter +//This will make sure in deconstruct the auto emitter is removed +function AudioDepSet(%obj,%set) +{ +if (ISobject(%obj)) + { + if (!%set && IsObject(%obj.emitter)) + { + %obj.emitter.delete(); + } + if (%set && !ISobject(%obj.emitter)) + { + //The only working check to keep faulty emitters from staying around + //Doesn't remove the console spam thougt.. :P + %obj.emitter = CreateAudioEmitter(%obj.getTransform(),%obj.Audioblock,%obj.lLogic); + if (isObject(%obj.emitter)) + %obj.emitter.addTofxGroup(1); + if ($audiopackloaded[%obj.emitter.filename]==1 && !Isfile(%obj.emitter.filename)) + { + disassemble(%obj.getdatablock(),%obj.owner,%obj); + } + else + { + //%obj.emitter.setTransform(%obj.getTransform()); + $audiopackloaded[%obj.emitter.filename]=1; + } + } + } +} + + + +// Just copy/past the emitter changemode since it needs almost totaly the same modes +function AudioDepImage::ChangeMode(%data,%plyr,%val,%level) +{ +if (%level == 0) + { + //Selecting emitter + if (!%plyr.expertSet) + { + if (!%plyr.packset[1]) + { + Parent::ChangeMode(%data,%plyr,%val,%level); + %plyr.packset[0] = GetWord($packSetting[AudioDepImage,%plyr.packset],2); + } + else + { + %plyr.packset = -1; + %plyr.packset[0] = nextsEmitter(%plyr.packset[0]+%val,%val); + %name = datablockGroup.getObject(%plyr.packset[0]).GetName(); + bottomPrint(%plyr.client,"sound pack set to play:"SPC %name,2,1); + } + } + //Selecting selection mode/PowerLogic/CloakLogic + else if (%plyr.expertSet > 0) + { + %set = %plyr.expertSet; + %image = %data.getName(); + %settings = $packSettings[%image,%set]; + + %plyr.packSet[%set] = %plyr.packSet[%set] + %val; + if (%plyr.packSet[%set] > getWord(%settings,0)) + %plyr.packSet[%set] = 0; + if (%plyr.packSet[%set] < 0) + %plyr.packSet[%set] = getWord(%settings,0); + + %packname = GetWords(%settings,2,getWordCount(%settings)); + %curset = $PackSetting[%image,%plyr.packSet[%set],%set]; + if (getWord(%settings,1) == -1) + %line = GetWords(%curset,0,getWordCount(%curset)); + else + %line = GetWords(%curset,0,getWord(%settings,1)); + bottomPrint(%plyr.client,%packname SPC "set to"SPC %line,2,1); + } + } +else + { + Parent::ChangeMode(%data,%plyr,%val,%level); + } +} + + +//Like promissed another browsing function. + + +function nextsEmitter(%start,%dir) +{ +if (%dir == 1) + { + for(%i = %start; %i < DatablockGroup.getCount() ; %i++) + { + if (datablockGroup.getObject(%i).description.volume !$= "")// && isFile(DatablockGroup.getObject(%i).filename)) + { + return %i; + } + } + return nextsEmitter(0,1); + } +else + { + for(%i = %start; %i > 0; %i--) + { + if (datablockGroup.getObject(%i).description.volume !$= "" ) //&& isFile(DatablockGroup.getObject(%i).filename)) + { + return %i; + } + } + return nextsEmitter(DatablockGroup.getCount(),-1); + } +} + + + +//Variant for createEmitter +//Can be modified to using custom audio files not found in datablocks +//Can also be futher extended to use other custom variables to people's desire +//Currently included looping mode and lifetime. +//Profile and description could be used.. however it will lessen the ability to +//modify the emitter. + +//it seems some clients deploying some sounds result in an faulty emitter +//I'l make sure those won't life to see the day.. but it's wierd still + +//Added the ability to use file name as %data, so you don't need datablocks.. :D + +function CreateAudioEmitter(%trans,%data,%forcelooping,%lifetime) +{ + +%dat = (IsObject(%data)); + +%desc = %data.description; + +if (%forcelooping) + %looping=1; +else + %looping = %desc.isLooping; + +%filename = %data.filename; + +%audio = new AudioEmitter() +{ +position = GetWords(%trans,0,2); +rotation = GetWords(%trans,3,6); +scale = "1 1 1"; +fileName = %dat ? %data.fileName : %data; +useProfileDescription = "0"; + +outsideAmbient = "1"; +volume = %dat ? %desc.volume : "1"; +isLooping = %dat ? %looping : "1"; +is3D = %dat ? %desc.is3D : "1"; +minDistance = %dat ? %desc.minDistance : "20"; +maxDistance = %dat ? %desc.maxDistance : "100"; +coneInsideAngle = %dat ? %desc.coneInsideAngle : "360"; +coneOutsideAngle = %dat ? %desc.coneOutsideAngle : "360"; +coneOutsideVolume = %dat ? %desc.coneOutsideVolume : "1"; +coneVector = %dat ? %desc.coneVector : "0 0 1"; +loopCount = %dat ? %desc.loopCount : "-1"; +minLoopGap = %dat ? %desc.minLoopGap : "0"; +maxLoopGap = %dat ? %desc.maxLoopGap : "0"; +type = "EffectAudioType"; +}; + +if (%lifetime !$="") + %audio.schedule(%lifetime.delete()); +return %audio; +} + + +/////////DISPENSER PACK////////// + +//Another nessted pack setting + +//Format = "%modes %lines %name" +//%modes gives the highest mode like the old settings +//%lines gives the amount of words in the settings which are the name of the mode +// -1 gives the entire content of the mode +// 2 would give the first 3 words of the mode +//%name gives the name of the pack as in %name "set to" %modename + +$expertSettings[DispenserDepImage] = "8 -1 Dispenser Pack:[Options]"; +$expertSetting[DispenserDepImage,0] = "[T2 Packs]"; +$expertSetting[DispenserDepImage,1] = "[Basic Building Parts]"; +$expertSetting[DispenserDepImage,2] = "[Base Assets]"; +$expertSetting[DispenserDepImage,3] = "[T2 Deployables]"; +$expertSetting[DispenserDepImage,4] = "[Decoration packs]"; +$expertSetting[DispenserDepImage,5] = "[Misc Deployables]"; +$expertSetting[DispenserDepImage,6] = "[Barrels]"; +$expertSetting[DispenserDepImage,7] = "[Weapons]"; +$expertSetting[DispenserDepImage,8] = "[Ammo]"; + + +//Hacky hacky way to get modes working.. hahaha +$packSettings[DispenserDepImage] = "8 1 Dispenser Pack:[T2 Packs]"; + +//Snagged from player.cs +$packSettings[DispenserDepImage,0] = "8 1 Dispenser Pack:[T2 Packs]"; +$packSetting[DispenserDepImage,0,0] = "[Cycle packs] cycle"; +$packSetting[DispenserDepImage,1,0] = "[Random pack] random"; +$packSetting[DispenserDepImage,2,0] = "Energy Pack EnergyPack"; +$packSetting[DispenserDepImage,3,0] = "Repair Pack RepairPack"; +$packSetting[DispenserDepImage,4,0] = "Shield Pack ShieldPack"; +$packSetting[DispenserDepImage,5,0] = "Cloak Pack CloakingPack"; +$packSetting[DispenserDepImage,6,0] = "Jammer Pack SensorJammerPack"; +$packSetting[DispenserDepImage,7,0] = "Ammunition Pack AmmoPack"; +$packSetting[DispenserDepImage,8,0] = "Satchel Charge SatchelCharge"; + +$packSettings[DispenserDepImage,1] = "8 1 Dispenser Pack:[Basic Building Parts]"; +$packSetting[DispenserDepImage,0,1] = "[Cycle packs] cycle"; +$packSetting[DispenserDepImage,1,1] = "[Random pack] random"; +$packSetting[DispenserDepImage,2,1] = "Light beam spinedeployable"; +$packSetting[DispenserDepImage,3,1] = "Light walkway wWallDeployable"; +$packSetting[DispenserDepImage,4,1] = "Light BlastWall WallDeployable"; +$packSetting[DispenserDepImage,5,1] = "Medium beam mspineDeployable"; +$packSetting[DispenserDepImage,6,1] = "Medium Floor floorDeployable"; +$packSetting[DispenserDepImage,7,1] = "Force Field ForceFieldDeployable"; +$packSetting[DispenserDepImage,8,1] = "Gravity Field GravityFieldDeployable"; + + +$packSettings[DispenserDepImage,2] = "9 1 Dispenser Pack:[Base Assets]"; +$packSetting[DispenserDepImage,0,2] = "[Cycle packs] cycle"; +$packSetting[DispenserDepImage,1,2] = "[Random pack] random"; +$packSetting[DispenserDepImage,2,2] = "Large Inventory-station LargeInventoryDeployable"; +$packSetting[DispenserDepImage,3,2] = "Medium-Sensor Pack MediumSensorDeployable"; +$packSetting[DispenserDepImage,4,2] = "Large-Sensor Pack LargeSensorDeployable"; +$packSetting[DispenserDepImage,5,2] = "Logo-Projector Pack LogoProjectorDeployable"; +$packSetting[DispenserDepImage,6,2] = "Deployable Turret-Base TurretBasePack"; +$packSetting[DispenserDepImage,7,2] = "Solar-Panel Pack SolarPanelDeployable"; +$packSetting[DispenserDepImage,8,2] = "Generator Pack GeneratorDeployable"; +$packSetting[DispenserDepImage,9,2] = "Switch Pack SwitchDeployable"; + +$packSettings[DispenserDepImage,3] = "6 1 Dispenser Pack:[T2 Deployables]"; +$packSetting[DispenserDepImage,0,3] = "[Cycle packs] cycle"; +$packSetting[DispenserDepImage,1,3] = "[Random pack] random"; +$packSetting[DispenserDepImage,2,3] = "Motion-Sensor Pack MotionSensorDeployable"; +$packSetting[DispenserDepImage,3,3] = "Pulse-Sensor Pack PulseSensorDeployable"; +$packSetting[DispenserDepImage,4,3] = "Landspike Turret TurretOutdoorDeployable"; +$packSetting[DispenserDepImage,5,3] = "SpiderClamp Turret TurretIndoorDeployable"; +$packSetting[DispenserDepImage,6,3] = "Inventory Station InventoryDeployable"; + +$packSettings[DispenserDepImage,4] = "7 1 Dispenser Pack:[Decoration packs]"; +$packSetting[DispenserDepImage,0,4] = "[Cycle packs] cycle"; +$packSetting[DispenserDepImage,1,4] = "[Random pack] random"; +$packSetting[DispenserDepImage,2,4] = "Decoration Pack DecorationDeployable"; +$packSetting[DispenserDepImage,3,4] = "Crate Pack PulseSensorDeployable"; +$packSetting[DispenserDepImage,4,4] = "Light Pack LightDeployable"; +$packSetting[DispenserDepImage,5,4] = "Emitter Pack EmitterDepPack"; +$packSetting[DispenserDepImage,6,4] = "Audio Pack AudioDepPack"; +$packSetting[DispenserDepImage,7,4] = "Tree Pack TreeDeployable"; + +$packSettings[DispenserDepImage,5] = "15 1 Dispenser Pack:[Misc Deployables]"; +$packSetting[DispenserDepImage,0,5] = "[Cycle packs] cycle"; +$packSetting[DispenserDepImage,1,5] = "[Random pack] random"; +$packSetting[DispenserDepImage,2,5] = "Jump Pad JumpadDeployable"; +$packSetting[DispenserDepImage,3,5] = "Teleport Pad TelePadPack"; +$packSetting[DispenserDepImage,4,5] = "Tripwire Pack TripwireDeployable"; +$packSetting[DispenserDepImage,5,5] = "Escape Pod EscapePodDeployable"; +$packSetting[DispenserDepImage,6,5] = "Pack Dispenser DispenserDepPack"; +$packSetting[DispenserDepImage,7,5] = "Detonation pack DetonationDeppack"; +$packSetting[DispenserDepImage,8,5] = "Energize pack EnergizerDeployable"; +$packSetting[DispenserDepImage,9,5] = "Disc turret DiscTurretDeployable"; +$packSetting[DispenserDepImage,10,5] = "Laser turret TurretLaserDeployable"; +$packSetting[DispenserDepImage,11,5] = "Rack Turret TurretMissileRackDeployable"; +$packSetting[DispenserDepImage,12,5] = "Anti Turret TurretMpm_Anti_Deployable"; +$packSetting[DispenserDepImage,13,5] = "MpmFuel pack MpmFuelPack"; +$packSetting[DispenserDepImage,14,5] = "MpmAmmo pack MpmAmmoPack"; +$packSetting[DispenserDepImage,15,5] = "Mpm TargetBeacon Mpm_BeaconPack"; + + + +$packSettings[DispenserDepImage,6] = "6 1 Dispenser Pack:[Decoration packs]"; +$packSetting[DispenserDepImage,0,6] = "[Cycle packs] cycle"; +$packSetting[DispenserDepImage,1,6] = "[Random pack] random"; +$packSetting[DispenserDepImage,2,6] = "ELF Barrel ELFBarrelPack"; +$packSetting[DispenserDepImage,3,6] = "Mortar Barrel MortarBarrelPack"; +$packSetting[DispenserDepImage,4,6] = "Plasma Barrel PlasmaBarrelPack"; +$packSetting[DispenserDepImage,5,6] = "AA Barrel AABarrelPack"; +$packSetting[DispenserDepImage,6,6] = "Missile Barrel MissileBarrelPack"; + +$packSettings[DispenserDepImage,7] = "17 1 Dispenser Pack:[Weapons]"; +$packSetting[DispenserDepImage,0,7] = "[Cycle packs] cycle"; +$packSetting[DispenserDepImage,1,7] = "[Random pack] random"; +$packSetting[DispenserDepImage,2,7] = "Blaster gun Blaster"; +$packSetting[DispenserDepImage,3,7] = "Plasma Rifle Plasma"; +$packSetting[DispenserDepImage,4,7] = "Quad Chaingun Chaingun"; +$packSetting[DispenserDepImage,5,7] = "Spinfusor lauchner Disc"; +$packSetting[DispenserDepImage,6,7] = "Grenade Launcher GrenadeLauncher"; +$packSetting[DispenserDepImage,7,7] = "Laser Rifle SniperRifle"; +$packSetting[DispenserDepImage,8,7] = "ELF Projector ELFGun"; +$packSetting[DispenserDepImage,9,7] = "Fusion Mortar Mortar"; +$packSetting[DispenserDepImage,10,7] = "Missile Launcher MissileLauncher"; +$packSetting[DispenserDepImage,11,7] = "Shock lance ShockLance"; +$packSetting[DispenserDepImage,12,7] = "Construction Tool ConstructionTool"; +$packSetting[DispenserDepImage,13,7] = "Nerf Gun NerfGun"; +$packSetting[DispenserDepImage,14,7] = "NerfBall Launcher NerfBallLauncher"; +$packSetting[DispenserDepImage,15,7] = "Super Chaingun SuperChaingun"; +$packSetting[DispenserDepImage,16,7] = "Transport gun Transgun"; +$packSetting[DispenserDepImage,17,7] = "Grapler gun TractorGun"; + +$packSettings[DispenserDepImage,8] = "9 1 Dispenser Pack:[Ammo]"; +$packSetting[DispenserDepImage,0,8] = "[Cycle packs] cycle"; +$packSetting[DispenserDepImage,1,8] = "[Random pack] random"; +$packSetting[DispenserDepImage,2,8] = "Plasma Ammo PlasmaAmmo"; +$packSetting[DispenserDepImage,3,8] = "Disc Ammo DiscAmmo"; +$packSetting[DispenserDepImage,4,8] = "GrenadeLaucher Ammo GrenadeLauncherAmmo"; +$packSetting[DispenserDepImage,5,8] = "FusionMortar Ammo MortarAmmo"; +$packSetting[DispenserDepImage,6,8] = "MissileLauncher Ammo MissileLauncherAmmo"; +$packSetting[DispenserDepImage,7,8] = "Chaingun Ammo ChaingunAmmo"; +$packSetting[DispenserDepImage,8,8] = "NerfBallLauncher Ammo NerfBallLauncherAmmo"; +$packSetting[DispenserDepImage,9,8] = "SuperChaingun Ammo SuperChaingunAmmo"; + + +///(Arg my poor fingers.. :() + + +datablock ParticleData( DispenserEffectParticle ) +{ + dragCoeffiecient = 0.0; + gravityCoefficient = 0.0; + inheritedVelFactor = 0.0; + + lifetimeMS = 250; + lifetimeVarianceMS = 100; + + textureName = "flarebase"; + + useInvAlpha = false; + + spinRandomMin = -360.0; + spinRandomMax = 360.0; + + colors[0] = "0.4 0.4 0.4 1.0"; + colors[1] = "0.3 0.3 0.3 0.1"; + colors[2] = "0.0 0.0 0.0 0.0"; + sizes[0] = 0.4; + sizes[1] = 0.5; + sizes[2] = 0.7; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; +}; + +datablock ParticleEmitterData( DispenserEffectEmitter ) +{ + ejectionPeriodMS = 5; + periodVarianceMS = 1; + + ejectionVelocity = 5.0; // A little oomph at the back end + velocityVariance = 2.0; + + thetaMin = 20.0; + thetaMax = 30.0; + phiReferenceVel = "0"; + phiVariance = "360"; + + orientParticles = False; + orientOnVelocity = False; + + particles = "DispenserEffectParticle"; +}; + + +datablock StaticShapeData(DispenserDep) : DeployedCrate +{ + shapeFile = "stackable4m.dts"; + needsPower = true; +}; + +datablock ShapeBaseImageData(DispenserDepImage) { + mass = 1; + emap = true; + shapeFile = "stackable4m.dts"; + item = DispenserDepPack; + mountPoint = 1; + offset = "0 -0.18 -0.5"; + deployed = DispenserDep; + heatSignature = 0; + + stateName[0] = "Idle"; + stateTransitionOnTriggerDown[0] = "Activate"; + + stateName[1] = "Activate"; + stateScript[1] = "onActivate"; + stateTransitionOnTriggerUp[1] = "Idle"; + + isLarge = true; + maxDepSlope = 360; + deploySound = ItemPickupSound; + + minDeployDis = 0.5; + maxDeployDis = 50.0; +}; + +datablock ItemData(DispenserDepPack) { + className = Pack; + catagory = "Deployables"; + shapeFile = "stackable4m.dts"; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 1; + rotate = true; + image = "DispenserDepImage"; + pickUpName = "an pack Dispenser"; + heatSignature = 0; + emap = true; + }; + +function DispenserDepPack::onPickup(%this, %obj, %shape, %amount) { + // created to prevent console errors +} + +function DispenserDep::gainPower(%data, %obj) +{ +respawnpack(%obj); +} + +function DispenserDep::losePower(%data, %obj) +{ +if (isObject(%obj.emitter)) + %obj.emitter.delete(); +} + + + +function DispenserDepImage::onDeploy(%item, %plyr, %slot) { + + %playerVector = vectorNormalize(-1 * getWord(%plyr.getEyeVector(),1) SPC getWord(%plyr.getEyeVector(),0) SPC "0"); + %item.surfaceNrm2 = %playerVector; + %rot = fullRot(%item.surfaceNrm,%item.surfaceNrm2); + + %deplObj = new StaticShape() + { + dataBlock = "DispenserDep"; + scale = "1.5 1.5 0.5"; + }; + + // set orientation + %deplObj.setTransform(%item.surfacePt SPC %rot); + + // set the recharge rate right away + if (%deplObj.getDatablock().rechargeRate) + %deplObj.setRechargeRate(%deplObj.getDatablock().rechargeRate); + + // set team, owner, and handle + %deplObj.team = %plyr.client.Team; + %deplObj.setOwner(%plyr); + + + %set1 = %plyr.packSet ? %plyr.packSet : 0; + %set2 = %plyr.expertSet ? %plyr.expertSet : 0; + %name = GetWord($packSetting[DispenserDepImage, %set1,%set2],2); + + %deplObj.packblock = %name; + %deplObj.set1 = %set1; + %deplObj.set2 = %set2; + + // place the deployable in the MissionCleanup/Deployables group (AI reasons) + addToDeployGroup(%deplObj); + + //let the AI know as well... + AIDeployObject(%plyr.client, %deplObj); + + // play the deploy sound + serverPlay3D(%item.deploySound, %deplObj.getTransform()); + + // increment the team count for this deployed object + $TeamDeployedCount[%plyr.team, %item.item]++; + + addDSurface(%item.surface,%deplObj); + %deplObj.powerFreq = %plyr.powerFreq; + checkPowerObject(%deplObj); + respawnpack(%deplObj); + + if (!%plyr.client.isAdmin) + { + %plyr.unmountImage(%slot); + %plyr.decInventory(%item.item, 1); + } + + return %deplObj; +} + +function DispenserDep::onDestroyed(%this,%obj,%prevState) { + if (%obj.isRemoved) + return; + %obj.isRemoved = true; + if (isObject(%obj.emitter)) + %obj.emitter.delete(); + Parent::onDestroyed(%this,%obj,%prevState); + $TeamDeployedCount[%obj.team, DispenserDepPack]--; + remDSurface(%obj); + %obj.schedule(500, "delete"); +} + +function DispenserDepImage::onMount(%data, %obj, %node) { + displayPowerFreq(%obj); + %obj.hasEmpack = true; // not needed anymore + %obj.packSet = 0; + %obj.packSet[0] = 0; + %obj.packSet[1] = 0; + %obj.packSet[2] = 0; + %obj.packSet[3] = 0; +} + +function DispenserDepImage::onUnmount(%data, %obj, %node) { + %obj.hasEmpack = ""; // not needed anymore + %obj.packSet = 0; + %obj.packSet[0] = 0; + %obj.packSet[1] = 0; + %obj.packSet[2] = 0; + %obj.packSet[3] = 0; +} + + + +//Respawns dispenser's item. + +function respawnpack(%disp,%override) +{ +if ((!IsObject(%disp.pack)) && isObject(%disp)) + { + %name = %disp.packblock; + %set1 = %disp.set1; + %set2 = %disp.set2; + + if (%name $= "cycle") + { + %disp.set1++; + %max = GetWord($packSettings[DispenserDepImage,%set2 ],0); + if (%disp.set1 > %max || %disp.set1 < 2) + %disp.set1 = 2; + %name = GetWord($packSetting[DispenserDepImage, %disp.set1,%set2],2); + } + else if (%name $= "random") + { + %max = GetWord($packSettings[DispenserDepImage,%set2 ],0); + %set1 = mFloor(getRandom()*(%max-2) +2); + %name = GetWord($packSetting[DispenserDepImage, %set1,%set2],2); + } + %pack = new Item() + { + dataBlock = %name; + static = false; + rotate = true; + }; + %pack.startFade(0,0,1); + %pos = VectorAdd(RealVec(%disp,"0 0 1"),%disp.getEdge("0 0 1")); + %pack.setTransform(%pos SPC "0 0 1" SPC getRandom()*$Pi*2); + %em = createLifeEmitter(%pos,DispenserEffectEmitter,1000); + %pack.startFade(1000,0,0); + %em.setRotation(%disp.getRotation); + %pack.dispenser = %disp; + %disp.emitter = %pack; //Lil hook to make it get removed when disas + %disp.pack = %pack; + %pack.addTofxGroup(2); + } +} + +//Not much has changed.. :D + +function DispenserDepImage::ChangeMode(%data,%plyr,%val,%level) +{ +if (%level == 0) + { + if (%plyr.expertset $= "") + %plyr.expertset = 0; + //Selecting Dispenser + %set = %plyr.expertSet $= "" ? 0 : %plyr.expertSet; + %image = %data.getName(); + %settings = $packSettings[%image,%set]; + + %plyr.packSet = %plyr.packSet + %val; + if (%plyr.packSet > getWord(%settings,0)) + %plyr.packSet = 0; + if (%plyr.packSet < 0) + %plyr.packSet = getWord(%settings,0); + + %packname = GetWords(%settings,2,getWordCount(%settings)); + %curset = $PackSetting[%image,%plyr.packSet,%set]; + if (getWord(%settings,1) == -1) + %line = GetWords(%curset,0,getWordCount(%curset)); + else + %line = GetWords(%curset,0,getWord(%settings,1)); + bottomPrint(%plyr.client,%packname SPC "set to"SPC %line,2,1); + + } +else + { + Parent::ChangeMode(%data,%plyr,%val,%level); + } +} + +/////////Detonation PACK////////// + + +$expertSettings[DetonationDepImage] = "2 -1 Detonation Pack:[Options]"; + +$expertSetting[DetonationDepImage,0] = "Select Payload"; +$expertSetting[DetonationDepImage,1] = "Select Detonation logic"; +$expertSetting[DetonationDepImage,2] = "Select Detonation Time"; + +$packSettings[DetonationDepImage] = "12 1 Detonation Pack:[Payload]"; +$packSetting[DetonationDepImage,0] = "Dud Explosion 5"; +$packSetting[DetonationDepImage,1] = "Repair Pulse 20"; +$packSetting[DetonationDepImage,2] = "Cloack Pulse 20"; +$packSetting[DetonationDepImage,3] = "Decon Pulse 20"; +$packSetting[DetonationDepImage,4] = "ESP Pulse 60"; +$packSetting[DetonationDepImage,5] = "Morph Pulse 60"; +$packSetting[DetonationDepImage,6] = "Ion Zap 30"; +$packSetting[DetonationDepImage,7] = "Mortar Fountain 30"; +$packSetting[DetonationDepImage,8] = "Bomber Crash 30"; +$packSetting[DetonationDepImage,9] = "Satchel Charge 30"; +$packSetting[DetonationDepImage,10] = "Atommic NukeCannon 120"; +$packSetting[DetonationDepImage,11] = "ArrowIV 150ktNuke 180"; +$packSetting[DetonationDepImage,12] = "Dark Hole 360"; + +$packSettings[DetonationDepImage,1] = "4 -1 Detonation Pack: [Detonation Logic]"; +$packSetting[DetonationDepImage,0,1] = "Detonate when armed"; +$packSetting[DetonationDepImage,1,1] = "Detonate when powered"; +$packSetting[DetonationDepImage,2,1] = "Detonate when not powered"; +$packSetting[DetonationDepImage,3,1] = "Detonate when deconstructed"; +$packSetting[DetonationDepImage,4,1] = "Detonate when destroyed"; + +$packSettings[DetonationDepImage,2] = "7 -1 Detonation Pack: [Detonation Time]"; +$packSetting[DetonationDepImage,0,2] = "3 Seconds"; +$packSetting[DetonationDepImage,1,2] = "5 Seconds"; +$packSetting[DetonationDepImage,2,2] = "10 Secconds"; +$packSetting[DetonationDepImage,3,2] = "20 Seconds"; +$packSetting[DetonationDepImage,4,2] = "30 Seconds"; +$packSetting[DetonationDepImage,5,2] = "60 Seconds"; +$packSetting[DetonationDepImage,6,2] = "120 Seconds"; +$packSetting[DetonationDepImage,7,2] = "600 Seconds"; + + +datablock StaticShapeData(DetonationDep) : DeployedCrate +{ + shapeFile = "stackable2l.dts"; + needsPower = true; + targetNameTag = 'Detonation'; + targetTypeTag = ''; +}; + +datablock StaticShapeData(DetonationDepArm) : DeployedCrate +{ + shapeFile = "stackable4m.dts"; + needsPower = true; +}; + + + +datablock ShapeBaseImageData(DetonationDepImage) { + mass = 1; + emap = true; + shapeFile = "stackable2l.dts"; + item = DetonationDepPack; + mountPoint = 1; + offset = "0 -1 -1"; + deployed = DetonationDepImage; + heatSignature = 0; + + stateName[0] = "Idle"; + stateTransitionOnTriggerDown[0] = "Activate"; + + stateName[1] = "Activate"; + stateScript[1] = "onActivate"; + stateTransitionOnTriggerUp[1] = "Idle"; + + isLarge = true; + maxDepSlope = 360; + deploySound = ItemPickupSound; + + minDeployDis = 0.5; + maxDeployDis = 50.0; +}; + +datablock ItemData(DetonationDepPack) { + explosion = SatchelMainExplosion; + underwaterExplosion = UnderwaterSatchelMainExplosion; + className = Pack; + catagory = "Deployables"; + shapeFile = "stackable2l.dts"; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 1; + rotate = true; + image = "DetonationDepImage"; + pickUpName = "an Detonation pack"; + heatSignature = 0; + emap = true; +armDelay = 3000; + maxDamage = 0.6; + + kickBackStrength = 4000; + + }; + +function DetonationDepPack::onPickup(%this, %obj, %shape, %amount) { + // created to prevent console errors +} + +function DetonationDep::gainPower(%data, %obj) +{ +if (%obj.dlogic==1 && %obj.armed) + { + %obj.detsched = schedule(%obj.dettime*1000,%obj,"DetonationDepDetonate",%obj); + PlaydetTimer(%obj,%obj.dettime); + } +else if (%obj.dlogic == 1) + { + %obj.wantdet = 1; + } +else if (%obj.dlogic == 2) + { + if (%obj.armed) + serverplay3d(MTCThinkSound,%obj.getTransform()); + StopDetTimer(%obj); + //Cancel(%Obj.armsch); + %obj.wantdet = 0; + Cancel(%obj.detsched); + } +} + +function DetonationDep::losePower(%data, %obj) +{ +if (%obj.dlogic==2 && %obj.armed) + { + %obj.detsched = schedule(%obj.dettime*1000,%obj,"DetonationDepDetonate",%obj); + PlaydetTimer(%obj,%obj.dettime); + } +else if (%obj.dlogic == 2) + { + %obj.wantdet = 1; + } +else if (%obj.dlogic == 1) + { + if (%obj.armed) + serverplay3d(MTCThinkSound,%obj.getTransform()); + StopDetTimer(%obj); + //Cancel(%Obj.armsch); + %obj.wantdet = 0; + Cancel(%obj.detsched); + } +} + + + + +function DetonationDepImage::onDeploy(%item, %plyr, %slot) { + + if (!$Host::SatchelChargeEnabled) + { + messageAll("", "\c2"@ %plyr.client.namebase @" tried to deploy a Detonation pack."); + %plyr.unmountImage(%slot); + %plyr.decInventory(%item.item, 1); + return; + } + + %playerVector = vectorNormalize(-1 * getWord(%plyr.getEyeVector(),1) SPC getWord(%plyr.getEyeVector(),0) SPC "0"); + %item.surfaceNrm2 = %playerVector; + %rot = fullRot(%item.surfaceNrm,%item.surfaceNrm2); + + %deplObj = new StaticShape() + { + dataBlock = "DetonationDep"; + scale = "0.4 0.4 1.2"; + }; + %Arm1 = new StaticShape() + { + dataBlock = "DetonationDeparm"; + scale = "2 2.2 2"; + }; + %arm2= new StaticShape() + { + dataBlock = "DetonationDeparm"; + scale = "2 2.2 2"; + }; + %arm3= new StaticShape() + { + dataBlock = "DetonationDeparm"; + scale = "0.8 0.8 0.4"; + }; + %arm4= new StaticShape() + { + dataBlock = "DetonationDeparm"; + scale = "0.8 0.8 0.4"; + }; + %deplObj.ownername = %plyr.client.namebase; + setTargetName(%deplObj.target,addTaggedString(%plyr.client.namebase SPC "\'s detonation pack [arming]")); + if (%deplObj.getTarget() != -1) + setTargetSensorGroup(%deplObj.getTarget(), %plyr.client.team); + + %rot1=rotadd(%rot,"0 1 0 -1.57"); + %rot2=rotadd(%rot,"0 1 0" SPC $Pi / 2); + %rot3=rotadd(%rot,"0 1 0" SPC -1*$Pi / 2); + // set orientation + %deplObj.setTransform(%item.surfacePt SPC %rot1); + %deplObj.setEdge(%item.surfacePt,"1 0 0"); + + %arm1.setTransform(%item.surfacePt SPC %rot); + %arm1.setEdge(%deplObj.getEdge("1 0 1"),"0 0 -1"); + %arm2.setTransform(%item.surfacePt SPC %rot); + %arm2.setEdge(%deplObj.getEdge("1 0 -1"),"0 0 -1"); + %arm3.setTransform(%item.surfacePt SPC %rot2); + %arm3.setEdge(%arm1.getEdge("-0.9 0 1"),"1 0 -1"); + %arm4.setTransform(%item.surfacePt SPC %rot3); + %arm4.setEdge(%arm2.getEdge("0.9 0 1"),"-1 0 -1"); + + //%deplobj.emitter = CreateEmitter(%deplObj.getEdge("0 0 0"),LoadingE); + //%deplobj.emitter.setRotation(%rot); + %emitter1 = CreateEmitter(%arm1.getEdge("0 0 1.2"),LoadingE2); + %emitter2 = CreateEmitter(%arm2.getEdge("0 0 1.2"),LoadingE2); + %deplobj.children=6; + %deplobj.child[0] = %arm1; + %deplobj.child[1] = %arm2; + %deplobj.child[2] = %arm3; + %deplobj.child[3] = %arm4; + %deplobj.child[4] = %emitter1; + %deplobj.child[5] = %emitter2; + + %arm1.parent = %deplobj; + %arm2.parent = %deplobj; + %arm3.parent = %deplobj; + %arm4.parent = %deplobj; + %deplobj.payload = %plyr.packset; + %deplobj.armtime = getWord($packSetting[DetonationDepImage,%plyr.packset],2); + %deplobj.dettime = getWord($packSetting[DetonationDepImage,%plyr.packset[2],2],0); + + // set the recharge rate right away + if (%deplObj.getDatablock().rechargeRate) + %deplObj.setRechargeRate(%deplObj.getDatablock().rechargeRate); + + // set team, owner, and handle + %deplObj.team = %plyr.client.Team; + %deplObj.setOwner(%plyr); + %arm1.team = %plyr.client.Team; + %arm1.setOwner(%plyr); + %arm2.team = %plyr.client.Team; + %arm2.setOwner(%plyr); + %arm3.team = %plyr.client.Team; + %arm3.setOwner(%plyr); + %arm4.team = %plyr.client.Team; + %arm4.setOwner(%plyr); + + %deplObj.dLogic = %plyr.packset[1]; + + + // place the deployable in the MissionCleanup/Deployables group (AI reasons) + addToDeployGroup(%deplObj); + + //let the AI know as well... + AIDeployObject(%plyr.client, %deplObj); + + // play the deploy sound + serverPlay3D(%item.deploySound, %deplObj.getTransform()); + + // increment the team count for this deployed object + $TeamDeployedCount[%plyr.team, %item.item]++; + + addDSurface(%item.surface,%deplObj); + %deplObj.powerFreq = %plyr.powerFreq; + checkPowerObject(%deplObj); + + //Warnings + %warns = mfloor(%deplobj.armtime/30); + for (%i =0; %i<%warns;%i++) + { + schedule(%i*30000,%deplObj,"bottomPrint",%plyr.client,"Detonation pack arming in" SPC (%warns-%i)*30 SPC"seconds",2,1); + } + %name = %plyr.client.namebase; + messageAll("", "\c2"@ %name @" deployed a Detonation pack.");//~wfx/misc/red_alert.wav"); + + %detpoint = new WayPoint() + { + position = %item.surfacept; + rotation = "1 0 0 0"; + scale = "1 1 1"; + name = "Arming Detonation pack"; + dataBlock = "WayPointMarker"; + lockCount = "0"; + homingCount = "0"; + }; + MissionCleanup.add(%detpoint); + %detpoint.schedule(5 * 1000, "delete"); + + %plyr.unmountImage(%slot); + %plyr.decInventory(%item.item, 1); + + %deplObj.armsch = schedule(%deplobj.armtime*1000,%deplObj,"ArmDetonationDep",%deplObj); + + return %deplObj; +} + + +function DetonationDep::onDestroyed(%this,%obj,%prevState) { + if (%obj.isRemoved) + return; + if (%obj.dlogic==4 && %obj.armed) + { + %obj.armed = 0; + DetonationDepDetonate(%obj); + } + %obj.isRemoved = true; + Parent::onDestroyed(%this,%obj,%prevState); + $TeamDeployedCount[%obj.team, DetonationDepPack]--; + remDSurface(%obj); + for(%i=0;%i<%obj.children;%i++) + { + if (isObject(%obj.child[%i])) + %obj.child[%i].schedule(500, "delete"); + } + %obj.schedule(500, "delete"); +} + +function DetonationDep::disassemble(%data,%plyr,%obj) { + if (!isObject(%obj) || %obj.isRemoved) + return; + if (%obj.dlogic==3 && %obj.armed) + { + DetonationDepDetonate(%obj); + //PlaydetTimer(%obj,%obj.dettime); + + } + for(%i=0;%i<%obj.children;%i++) + { + if (isObject(%obj.child[%i])) + %obj.child[%i].delete(); + } + Parent::disassemble(%data,%plyr,%obj); +} + +function DetonationDepArm::disassemble(%data,%plyr,%obj) { + Cancel(%Obj.armsch); + if (!isObject(%obj) || %obj.isRemoved) + return; + if (isObject(%obj.parent)) { + %obj.parent.getDatablock().disassemble(%plyr,%obj.parent); + } + Parent::disassemble(%data,%plyr,%obj); +} + +function StartArmDetonationDep(%obj) +{ +Cancel(%obj.detsched); +Cancel(%Obj.armsch); +StopDetTimer(%obj); +%obj.armed = 0; +setTargetName(%Obj.target,addTaggedString(%obj.owner.namebase SPC "\'s detonation pack [arming]")); +if (isObject(%obj.child[4])) + %obj.child[4].delete(); +if (isObject(%obj.child[5])) + %obj.child[5].delete(); +%obj.child[4] = CreateEmitter(%obj.child[0].getEdge("0 0 1.2"),LoadingE2); +%obj.child[5] = CreateEmitter(%obj.child[1].getEdge("0 0 1.2"),LoadingE2); + +%Obj.armsch = schedule(%obj.armtime*1000,%Obj,"ArmDetonationDep",%obj); +} + +function ArmDetonationDep(%obj) +{ +Cancel(%obj.detsched); +Cancel(%Obj.armsch); +StopDetTimer(%obj); + +setTargetName(%Obj.target,addTaggedString(%obj.ownername SPC "\'s detonation pack [armed]")); +serverplay3d(MTCThinkSound,%obj.getTransform()); + +if (isObject(%obj.child[4])) + %obj.child[4].delete(); +if (isObject(%obj.child[5])) + %obj.child[5].delete(); +%obj.child[4] = CreateEmitter(%obj.getEdge("0 0 0"),LoadingE); +%obj.child[4].setRotation(%obj.child[0].getrotation()); +%obj.armed = 1; + +if (%obj.dlogic == 0 || %obj.wantdet) + { + %obj.detsched = schedule(%obj.dettime*1000,%obj,"DetonationDepDetonate",%obj); + PlaydetTimer(%obj,%obj.dettime); + } +} + +function PlaydetTimer(%obj,%timeleft) +{ +StopDetTimer(%obj); +%times = "1 2 3 5 10 30 60"; +%obj.counting = 1; +for (%i=0;%i<7;%i++) + { + %tt = GetWord(%times,%i); + if (%tt<=%timeleft) + { + %point = %timeleft-%tt; + %obj.countsound[%i] = schedule(%point*1000,%obj,"PlaydetSound",%obj,GetWord(%times,%i)); + } + } +if (%obj.dlogic != 0) + { + //%time = (%obj.dettime < 30) ? 30 : %obj.dettime; + //%obj.countsound[8] = schedule(%timeleft*1000,%obj,"PlaydetTimer",%obj,%time); + } +} + +function StopDetTimer(%obj) +{ +%obj.counting = 0; +for (%i=0;%i<8;%i++) + { + Cancel(%obj.countsound[%i]); + } +} + +function PlaydetSound(%obj,%time) +{ +if (isObject(%obj) && %obj.counting) + { + setTargetName(%obj.target,addTaggedString(%obj.ownername SPC "\'s detonation pack ["@ %time @" seconds mark]")); + ServerPlay3D(MessageRecieveSound,%obj.getTransform()); + } +} + +function DetonationDepImage::onMount(%data, %obj, %node) { + displayPowerFreq(%obj); + %obj.hasEmpack = true; // not needed anymore + %obj.packSet = 0; + %obj.expertSet = 0; + %obj.packSet[0] = 0; + %obj.packSet[1] = 0; + %obj.packSet[2] = 0; +} + +function DetonationDepImage::onUnmount(%data, %obj, %node) { + %obj.hasEmpack = ""; // not needed anymore + %obj.packSet = 0; + %obj.expertSet = 0; + %obj.packSet[0] = 0; + %obj.packSet[1] = 0; + %obj.packSet[2] = 0; +} + + + +function DetonationDepImage::ChangeMode(%data,%plyr,%val,%level) +{ +if (%level == 0) + { + //Selecting Detonation + if (!%plyr.expertSet) + { + Parent::ChangeMode(%data,%plyr,%val,%level); + //%plyr.packset[0] = GetWord($packSetting[DetonationDepImage,%plyr.packset],2); + } + //Selecting selection mode/PowerLogic/CloakLogic + else if (%plyr.expertSet > 0) + { + %set = %plyr.expertSet; + %image = %data.getName(); + %settings = $packSettings[%image,%set]; + + %plyr.packSet[%set] = %plyr.packSet[%set] + %val; + if (%plyr.packSet[%set] > getWord(%settings,0)) + %plyr.packSet[%set] = 0; + if (%plyr.packSet[%set] < 0) + %plyr.packSet[%set] = getWord(%settings,0); + + %packname = GetWords(%settings,2,getWordCount(%settings)); + %curset = $PackSetting[%image,%plyr.packSet[%set],%set]; + if (getWord(%settings,1) == -1) + %line = GetWords(%curset,0,getWordCount(%curset)); + else + %line = GetWords(%curset,0,getWord(%settings,1)); + bottomPrint(%plyr.client,%packname SPC "set to"SPC %line,2,1); + } + } +else + { + Parent::ChangeMode(%data,%plyr,%val,%level); + } +} + +function DetonationDepDetonate(%obj) +{ +if (!%obj.payload) + { + //do nothing + } +else if (%obj.payload == 1) + { + Aidpulse(%obj.getTransform(),%obj.owner,0); + } +else if (%obj.payload == 2) + { + Aidpulse(%obj.getTransform(),%obj.owner,1); + } +else if (%obj.payload == 3) + { + Aidpulse(%obj.getTransform(),%obj.owner,2); + } +else if (%obj.payload == 4) + { + Aidpulse(%obj.getTransform(),%obj.owner,3); + } +else if (%obj.payload == 5) + { + Aidpulse(%obj.getTransform(),%obj.owner,4); + } +else if (%obj.payload == 6) + { + %obj.Zap(5000); + } +else if (%obj.payload == 7) + { + for (%i=0;%i<5;%i++) + { + %ranupvec = GetRandom()*2-1 SPC GetRandom()*2-1 SPC GetRandom()*1; + MortarShot.Create(%obj.getEdge("-2 0 0"),VectorScale(realvec(%obj,%ranupvec),0.5)); + } + } +else if (%obj.payload == 8) + { + for (%i=0;%i<5;%i++) + { + %ranupvec = GetRandom()*2-1 SPC GetRandom()*2-1 SPC GetRandom()*1; + BomberBomb.Create(%obj.getEdge("-2 0 0"),realvec(%obj,%ranupvec),VectorScale(realvec(%obj,%ranupvec),20)); + } + } +else if (%obj.payload == 9) + { + scatchelkaboom(%obj.getEdge("-2 0 0"),%obj.owner); + } +else if (%obj.payload == 10) + { + BigFatNukeDrop(%obj.getTransform()); + } +else if (%obj.payload == 11) + { + ShoulderNuclear.onExplode(%obj, %obj.getTransform()); + } +else if (%obj.payload == 12) + { + %pos = %obj.getTransform(); + %mask = $TypeMasks::StaticShapeObjectType | $TypeMasks::ForceFieldObjectType | $TypeMasks::InteriorObjectType; + %res = containerRayCast(%pos,"0 0 500",%mask, %obj); + if (%res) + %inside = 1; + dome(VectorAdd(%pos,"0 0" SPC (1-%inside)*200),60000,%inside); + } + if (!%obj.isRemoved) + { + if (%obj.payload == 0 || %obj.payload > 9) + %obj.setDamageState(Destroyed); + else + { + StartArmDetonationDep(%obj); + } + } +} + +function scatchelkaboom(%pos,%owner) +{ +%pack = new Item() + { + dataBlock = SatchelChargeThrown; + static = false; + rotate = true; + }; +//%pack.sourceObject = %owner.player; +//%pack.blowingUp=1; +%pack.setTransform(%pos); +%pack.armed = True; +%pack.Schedule(50,"setDamageState",Destroyed); +} + diff --git a/scripts/packs/blastfloor.cs b/scripts/packs/blastfloor.cs new file mode 100644 index 0000000..2bcaecc --- /dev/null +++ b/scripts/packs/blastfloor.cs @@ -0,0 +1,242 @@ +//--------------------------------------------------------- +// Deployable floor +//--------------------------------------------------------- + +datablock StaticShapeData(DeployedFloor) : StaticShapeDamageProfile { + className = "floor"; + shapeFile = "smiscf.dts"; + + maxDamage = 4; + destroyedLevel = 4; + disabledLevel = 3.5; + + isShielded = true; + energyPerDamagePoint = 30; + maxEnergy = 200; + rechargeRate = 0.25; + + explosion = HandGrenadeExplosion; + expDmgRadius = 3.0; + expDamage = 0.1; + expImpulse = 200.0; + + dynamicType = $TypeMasks::StaticShapeObjectType; + deployedObject = true; + cmdCategory = "DSupport"; + cmdIcon = CMDSensorIcon; + cmdMiniIconName = "commander/MiniIcons/com_deploymotionsensor"; + targetNameTag = 'Medium Blast floor'; + deployAmbientThread = true; + debrisShapeName = "debris_generic_small.dts"; + debris = DeployableDebris; + heatSignature = 0; + needsPower = true; +}; + +datablock ShapeBaseImageData(FloorDeployableImage) { + mass = 1; + emap = true; + shapeFile = "stackable1s.dts"; + item = FloorDeployable; + mountPoint = 1; + offset = "0 0 0"; + deployed = DeployedFloor; + heatSignature = 0; + + stateName[0] = "Idle"; + stateTransitionOnTriggerDown[0] = "Activate"; + + stateName[1] = "Activate"; + stateScript[1] = "onActivate"; + stateTransitionOnTriggerUp[1] = "Idle"; + + isLarge = false; + maxDepSlope = 360; // also see FloorDeployableImage::testSlopeTooGreat() + deploySound = ItemPickupSound; + + minDeployDis = 0.1; + maxDeployDis = 50.0; +}; + +datablock ItemData(FloorDeployable) { + className = Pack; + catagory = "Deployables"; + shapeFile = "stackable1s.dts"; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 1; + rotate = true; + image = "FloorDeployableImage"; + pickUpName = "a medium floor pack"; + heatSignature = 0; + emap = true; +}; + +function FloorDeployableImage::testSlopeTooGreat(%item) { + if (%item.surface) { + // Do we link with another Medium Floor? + if (%item.surface.getClassName() $= "StaticShape") { + if (%item.surface.getDataBlock().className $= "floor") { + %floor = 1; + } + } + if (%floor) { + if ($Host::Purebuild == true && $Host::Hazard::Enabled != true) + return getTerrainAngle(%item.surfaceNrm) > %item.maxDepSlope; + else + return getTerrainAngle(%item.surfaceNrm) > 1; + } + else + return getTerrainAngle(%item.surfaceNrm) > %item.maxDepSlope; + } +} + +function FloorDeployableImage::testObjectTooClose(%item) { + if ($Host::Purebuild == true && $Host::Hazard::Enabled != true) + return ""; + else { + %terrain = %item.surface.getClassName() $= "TerrainBlock"; + %interior = %item.surface.getClassName() $= "InteriorInstance"; + if (%item.surface.getClassName() $= "StaticShape") { + if (%item.surface.getDataBlock().className $= "floor") { + %floor = 1; + } + } + return !(%terrain || %interior || %floor); + } +} + +function FloorDeployableImage::testNoTerrainFound(%item) { + // don't check this for non-Landspike turret deployables +} + +function FloorDeployable::onPickup(%this, %obj, %shape, %amount) { + // created to prevent console errors +} + +function FloorDeployableImage::onDeploy(%item, %plyr, %slot) { + //Object + %className = "StaticShape"; + + %grounded = 0; + if (%item.surface.getClassName() $= TerrainBlock) + %grounded = 1; + + %playerVector = vectorNormalize(-1 * getWord(%plyr.getEyeVector(),1) SPC getWord(%plyr.getEyeVector(),0) SPC "0"); + + %rot = intRot("1 0 0 0",%playerVector); + + %scale = getWords($packSetting["floor",%plyr.packSet],0,2); + + if ($Host::ExpertMode == 1) + %scale = getWords(%scale,0,1) SPC firstWord($expertSetting["floor",%plyr.expertSet]); + + %surfaceAdjust = 1; + // Do we link with another Medium Floor? + if (%item.surface.getClassName() $= "StaticShape") { + if (%item.surface.getDataBlock().className $= "floor") { + %surfaceAdjust = 0; + // [[Most]] Get the relative x y location from the "pure" information. + %link = sidelink(%item.surface,%item.surfaceNrm,%item.surfacePt,getWords($packSetting["floor",%plyr.packSet],3,5),"0 0 -0.5"); + %location = getWords(%link,0,2); + %side = getWords(%link,3,5); + %dirside = getWords(%link,6,8); + // [[Most]] Set the rotation to match the surfaceNrm and match the side. + // The power of the full rotation system.. ;) + %rot = fullRot(%item.surfaceNrm,vectorScale(%dirside,-1)); + // [[Most]] Adjust the location to match the scale. + %adjust = vectorScale(%item.surfaceNrm,GetWord(%scale,2)); + %item.surfacePt = vectorSub(%location, %adjust); + } + } + + // If we do not link with another Medium Floor + if(%surfaceAdjust) { + %item.surfacePt = vectorSub(%item.surfacePt,"0 0" SPC getWord(%scale,2) - 1); // Rise 1 meter above surface + } + + %scale = vectorMultiply(%scale,1/4 SPC 1/3 SPC 2); + + %deplObj = new (%className)() { + dataBlock = %item.deployed; + scale = %scale; + }; + +//////////////////////////Apply settings////////////////////////////// + + // [[Location]]: + + // exact: + %deplObj.setTransform(%item.surfacePt SPC %rot); + + // misc info + addDSurface(%item.surface,%deplObj); + + // [[Settings]]: + + %deplObj.grounded = %grounded; + %deplObj.needsFit = 1; + + // [[Normal Stuff]]: + +// if(%deplObj.getDatablock().rechargeRate) +// %deplObj.setRechargeRate(%deplObj.getDatablock().rechargeRate); + + // set team, owner, and handle + %deplObj.team = %plyr.client.team; + %deplObj.setOwner(%plyr); + + // set power frequency + %deplObj.powerFreq = %plyr.powerFreq; + + // set the sensor group if it needs one + if (%deplObj.getTarget() != -1) + setTargetSensorGroup(%deplObj.getTarget(), %plyr.client.team); + + // place the deployable in the MissionCleanup/Deployables group (AI reasons) + addToDeployGroup(%deplObj); + + //let the AI know as well... + AIDeployObject(%plyr.client, %deplObj); + + // play the deploy sound + serverPlay3D(%item.deploySound, %deplObj.getTransform()); + + // increment the team count for this deployed object + $TeamDeployedCount[%plyr.team, %item.item]++; + + %deplObj.deploy(); + + // Power object + checkPowerObject(%deplObj); + + deployEffect(%deplObj,%item.surfacePt,%item.surfaceNrm,"floor"); + + return %deplObj; +} + +function DeployedFloor::onDestroyed(%this, %obj, %prevState) { + if (%obj.isRemoved) + return; + %obj.isRemoved = true; + Parent::onDestroyed(%this, %obj, %prevState); + $TeamDeployedCount[%obj.team, FloorDeployable]--; + remDSurface(%obj); + %obj.schedule(500, "delete"); + cascade(%obj); + fireBallExplode(%obj,1); +} + +function FloorDeployableImage::onMount(%data, %obj, %node) { + %obj.hasFloor = true; // set for floorcheck + %obj.packSet = 0; + %obj.expertSet = 0; + displayPowerFreq(%obj); +} + +function FloorDeployableImage::onUnmount(%data, %obj, %node) { + %obj.hasFloor = ""; + %obj.packSet = 0; + %obj.expertSet = 0; +} diff --git a/scripts/packs/blastwall.cs b/scripts/packs/blastwall.cs new file mode 100644 index 0000000..8118f33 --- /dev/null +++ b/scripts/packs/blastwall.cs @@ -0,0 +1,271 @@ +//--------------------------------------------------------- +// Deployable wall, Code by Parousia +//--------------------------------------------------------- + +datablock StaticShapeData(DeployedWall) : StaticShapeDamageProfile { + className = "wall"; + shapeFile = "Bmiscf.dts"; // dmiscf.dts, alternate + + maxDamage = 2; + destroyedLevel = 2; + disabledLevel = 1.5; + + isShielded = true; + energyPerDamagePoint = 60; + maxEnergy = 100; + rechargeRate = 0.25; + + explosion = HandGrenadeExplosion; + expDmgRadius = 3.0; + expDamage = 0.1; + expImpulse = 200.0; + + dynamicType = $TypeMasks::StaticShapeObjectType; + deployedObject = true; + cmdCategory = "DSupport"; + cmdIcon = CMDSensorIcon; + cmdMiniIconName = "commander/MiniIcons/com_deploymotionsensor"; + targetNameTag = 'Light Blast Wall'; + deployAmbientThread = true; + debrisShapeName = "debris_generic_small.dts"; + debris = DeployableDebris; + heatSignature = 0; + needsPower = true; +}; + +datablock ShapeBaseImageData(WallDeployableImage) { + mass = 1; + emap = true; + shapeFile = "stackable1s.dts"; + item = WallDeployable; + mountPoint = 1; + offset = "0 0 0"; + deployed = DeployedWall; + heatSignature = 0; + + stateName[0] = "Idle"; + stateTransitionOnTriggerDown[0] = "Activate"; + + stateName[1] = "Activate"; + stateScript[1] = "onActivate"; + stateTransitionOnTriggerUp[1] = "Idle"; + + isLarge = false; + maxDepSlope = 360; + deploySound = ItemPickupSound; + + minDeployDis = 0; + maxDeployDis = 50.0; +}; + +datablock ItemData(WallDeployable) { + className = Pack; + catagory = "Deployables"; + shapeFile = "stackable1s.dts"; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 1; + rotate = true; + image = "WallDeployableImage"; + pickUpName = "a light blast wall pack"; + heatSignature = 0; + emap = true; +}; + +function WallDeployableImage::testObjectTooClose(%item) { + return ""; +} + +function WallDeployableImage::testNoTerrainFound(%item) { + // don't check this for non-Landspike turret deployables +} + +function WallDeployable::onPickup(%this, %obj, %shape, %amount) { + // created to prevent console errors +} + +function WallDeployableImage::onDeploy(%item, %plyr, %slot) { + //Object + %className = "StaticShape"; + + %grounded = 0; + if (%item.surface.getClassName() $= TerrainBlock) + %grounded = 1; + + %playerVector = vectorNormalize(-1 * getWord(%plyr.getEyeVector(),1) SPC getWord(%plyr.getEyeVector(),0) SPC "0"); + + if (%item.surfaceinher == 0) { + if (vAbs(floorVec(%item.surfaceNrm,100)) $= "0 0 1") + %item.surfaceNrm2 = %playerVector; + else + %item.surfaceNrm2 = vectorNormalize(vectorCross(%item.surfaceNrm,"0 0 1")); + } + + %scale = "0.5 8 40"; // Search range for total blast wall size. + + %mCenter = "0 0 -0.5"; + %pad = pad(%item.surfacePt SPC %item.surfaceNrm SPC %item.surfaceNrm2,%scale,%mCenter); + %scale = getWords(%pad,0,2); + + %item.surfacePt = getWords(%pad,3,5); + %rot = getWords(%pad,6,9); + %offset = %plyr.packSet - 1; + if (%plyr.packSet == 3) { + %double = 1; + %offset = 1; + } + + %scale = vectorAdd(%scale,vectorScale("1.01 1.01" SPC %double,mAbs(%offset))); + + %pup = mCeil(getWord(%scale,0)/4); //4 = Avarage blast wall height. + %pside = mCeil(getWord(%scale,1)/4); //4 = Avarage blast wall width. + %upiece = getWord(%scale,0)/%pup; + %spiece = getWord(%scale,1)/%pside; + + %scale = vectorMultiply(%scale,1/4 SPC 1/3 SPC 2); + %dir = VectorNormalize(vectorSub(%item.surfacePt,%plyr.getposition())); + %adjust = vectorNormalize(vectorProject(%dir,vectorCross(%item.surfaceNrm,%item.surfaceNrm2))); +// %adjust = vectorNormalize(vectorCross(%item.surfaceNrm,%item.surfaceNrm2)); + + if (%plyr.packSet == 3) + %offset = Lev(vectorCouple(%dir,vectorCross(%item.surfaceNrm,%item.surfaceNrm2))); + + %adjust = vectorScale(%adjust,-0.5 * %offset); + + if ($Host::ExpertMode == 1 && %plyr.expertSet == 1) { + for (%x = 0;%x < %pup;%x++){ + for (%y = 0;%y < %pside;%y++){ + %scale = %upiece SPC %spiece SPC 0.5 + %double; + %scale = vectorMultiply(%scale,1/4 SPC 1/3 SPC 2); + %deplObj = new (%className)() { + dataBlock = %item.deployed; + scale = %scale; + }; + %up = vectorScale(%item.surfaceNrm,%upiece * (%x - (%pup / 2) + 0.5)); + %side = vectorScale(%item.surfaceNrm2,%spiece * (%y - (%pside / 2) + 0.5)); + %tadjust = vectorAdd(%up,vectorAdd(%side,%adjust)); + %deplObj.setTransform(vectorAdd(%item.surfacePt,%tadjust) SPC %rot); + + // [[Settings]]: + + %deplObj.grounded = %grounded; + %deplObj.Needsfit = 1; + addDSurface(%item.surface,%deplObj); + + // [Normal Stuff]]: + +// if(%deplObj.getDatablock().rechargeRate) +// %deplObj.setRechargeRate(%deplObj.getDatablock().rechargeRate); + + // set team, owner, and handle + %deplObj.team = %plyr.client.Team; + %deplObj.setOwner(%plyr); + + // set power frequency + %deplObj.powerFreq = %plyr.powerFreq; + + // set the sensor group if it needs one + if(%deplObj.getTarget() != -1) + setTargetSensorGroup(%deplObj.getTarget(), %plyr.client.team); + + // place the deployable in the MissionCleanup/Deployables group (AI reasons) + addToDeployGroup(%deplObj); + + // let the AI know as well... + AIDeployObject(%plyr.client, %deplObj); + + // play the deploy sound + serverPlay3D(%item.deploySound, %deplObj.getTransform()); + + // increment the team count for this deployed object + $TeamDeployedCount[%plyr.team, %item.item]++; + + %deplObj.deploy(); + } + } + } + else { + %deplObj = new (%className)() { + dataBlock = %item.deployed; + scale = %scale; + }; + + %deplObj.setTransform(vectorAdd(%item.surfacePt,%adjust) SPC %rot); + + // [[Settings]]: + + %deplObj.grounded = %grounded; + %deplObj.Needsfit = 1; + addDSurface(%item.surface,%deplObj); + + // [Normal Stuff]]: + +// if(%deplObj.getDatablock().rechargeRate) +// %deplObj.setRechargeRate(%deplObj.getDatablock().rechargeRate); + + // set team, owner, and handle + %deplObj.team = %plyr.client.Team; + %deplObj.setOwner(%plyr); + + // set power frequency + %deplObj.powerFreq = %plyr.powerFreq; + + // set the sensor group if it needs one + if(%deplObj.getTarget() != -1) + setTargetSensorGroup(%deplObj.getTarget(), %plyr.client.team); + + // place the deployable in the MissionCleanup/Deployables group (AI reasons) + addToDeployGroup(%deplObj); + + //let the AI know as well... + AIDeployObject(%plyr.client, %deplObj); + + // play the deploy sound + serverPlay3D(%item.deploySound, %deplObj.getTransform()); + + // increment the team count for this deployed object + $TeamDeployedCount[%plyr.team, %item.item]++; + + %deplObj.deploy(); + } + + // Power object + checkPowerObject(%deplObj); + + deployEffect(%deplObj,%item.surfacePt,%item.surfaceNrm,"pad"); + + return %deplObj; +} + +function DeployedWall::onDestroyed(%this, %obj, %prevState) { + if (%obj.isRemoved) + return; + %obj.isRemoved = true; + Parent::onDestroyed(%this, %obj, %prevState); + $TeamDeployedCount[%obj.team, WallDeployable]--; + remDSurface(%obj); + %obj.schedule(500, "delete"); + cascade(%obj); + fireBallExplode(%obj,1); +} + +function WallDeployableImage::onMount(%data, %obj, %node) { + %obj.hasBlast = true; // set for blastcheck + %obj.packSet = 0; + %obj.expertSet = 0; + displayPowerFreq(%obj); +} + +function WallDeployableImage::onUnmount(%data, %obj, %node) { + %obj.hasBlast = ""; + %obj.packSet = 0; + %obj.expertSet = 0; +} + +function doorfunction(%player,%door) +{ +%vec = VectorSub(%door,%player); +%dir = VectorNormalize(%vec); +%nrm = topVec(VirVec(%door,%dir)); +} diff --git a/scripts/packs/blastwwall.cs b/scripts/packs/blastwwall.cs new file mode 100644 index 0000000..66f4c01 --- /dev/null +++ b/scripts/packs/blastwwall.cs @@ -0,0 +1,225 @@ +//--------------------------------------------------------- +// Deployable wall, Code by Parousia +//--------------------------------------------------------- + +datablock StaticShapeData(DeployedwWall) : StaticShapeDamageProfile { + className = "wwall"; + shapeFile = "smiscf.dts"; + + maxDamage = 0.5; + destroyedLevel = 0.5; + disabledLevel = 0.3; + + isShielded = true; + energyPerDamagePoint = 240; + maxEnergy = 50; + rechargeRate = 0.25; + + explosion = HandGrenadeExplosion; + expDmgRadius = 3.0; + expDamage = 0.1; + expImpulse = 200.0; + + dynamicType = $TypeMasks::StaticShapeObjectType; + deployedObject = true; + cmdCategory = "DSupport"; + cmdIcon = CMDSensorIcon; + cmdMiniIconName = "commander/MiniIcons/com_deploymotionsensor"; + targetNameTag = 'Light Walk Way'; + deployAmbientThread = true; + debrisShapeName = "debris_generic_small.dts"; + debris = DeployableDebris; + heatSignature = 0; + needsPower = true; +}; + +datablock ShapeBaseImageData(wWallDeployableImage) { + mass = 1; + emap = true; + shapeFile = "stackable1s.dts"; + item = wwallDeployable; + mountPoint = 1; + offset = "0 0 0"; + deployed = DeployedwWall; + heatSignature = 0; + + stateName[0] = "Idle"; + stateTransitionOnTriggerDown[0] = "Activate"; + + stateName[1] = "Activate"; + stateScript[1] = "onActivate"; + stateTransitionOnTriggerUp[1] = "Idle"; + + isLarge = false; + maxDepSlope = 360; + deploySound = ItemPickupSound; + + minDeployDis = 0; + maxDeployDis = 50.0; +}; + +datablock ItemData(wwallDeployable) { + className = Pack; + catagory = "Deployables"; + shapeFile = "stackable1s.dts"; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 1; + rotate = true; + image = "wWallDeployableImage"; + pickUpName = "a light walkway pack"; + heatSignature = 0; + emap = true; +}; + +function wWallDeployableImage::testObjectTooClose(%item) { + return ""; +} + +function wWallDeployableImage::testNoTerrainFound(%item) { + // don't check this for non-Landspike turret deployables +} + +function wwallDeployable::onPickup(%this, %obj, %shape, %amount) { + // created to prevent console errors +} + +function wWallDeployableImage::onDeploy(%item, %plyr, %slot) { + //Object + %className = "StaticShape"; + + %grounded = 0; + if (%item.surface.getClassName() $= TerrainBlock) + %grounded = 1; + + %playerVector = vectorNormalize(-1 * getWord(%plyr.getEyeVector(),1) SPC getWord(%plyr.getEyeVector(),0) SPC "0"); + + %rot = intRot("1 0 0 0",%playerVector); + + %scale ="5 5 0.5"; + + if ($Host::ExpertMode == 1) { + if (%plyr.expertSet == 2) + %scale = getWord(%scale,0) * 2 SPC getWords(%scale,1,2); + if (%plyr.expertSet == 3) + %scale = getWord(%scale,0) SPC getWord(%scale,1) * 2 SPC getWord(%scale,2); + } + + %surfaceAdjust = 1; + // Do we link with another shape? + if (%item.surface.getClassName() $= "StaticShape") { + %surfaceAdjust = 0; + // [[Most]] Get the relative x y location from the "pure" informtation. + %link = sidelink(%item.surface,%item.surfaceNrm,%item.surfacePt,%scale,"0 0 -0.5"); + %location = getWords(%link,0,2); + %side = getWords(%link,3,5); + %dirside = getWords(%link,6,8); + // [[Most]] Set the rotation to match the surfaceNrm and match the side. + // The power of the full rotation system.. ;) + %rot = fullRot(%item.surfaceNrm,%dirside); + // [[Most]] Adjust the location to match the scale. + %adjust = vectorScale(%item.surfaceNrm,getWord(%scale,2)); + %item.surfacePt = vectorSub(%location, %adjust); + } + + // If we do not link with another shape + if(%surfaceAdjust) { + %item.surfacePt = vectorSub(%item.surfacePt,"0 0" SPC getWord(%scale,2) - 1); // Rise 1 meter above surface + } + + %scale = vectorMultiply(%scale,1/4 SPC 1/3 SPC 2); + + %deplObj = new (%className)() { + dataBlock = %item.deployed; + scale = %scale; + }; + + %deplObj.setTransform(%item.surfacePt SPC %rot); + + %axis = vectorCross(virvec(%item.surface,%item.surfaceNrm),virvec(%item.surface,%side)); + %axis = vectorScale(%axis,-1); + %vec1 = vectorScale(virvec(%item.surface,%side),0.5); + %vec2 = vectorAdd(vectorScale(virvec(%item.surface,%item.surfaceNrm),-0.5),"0 0 -0.5"); + + deployEffect(%deplObj,%location,%side,"walk"); + %angle = getWord($packSetting["walk",%plyr.packSet],0)/180*$Pi; + %deplObj.setTransform(remoterotate(%deplObj,%axis SPC %angle,%item.surface,vectorAdd(%vec2,%vec1))); + + if ($Host::ExpertMode == 1 && %plyr.expertSet == 1) { + %v = getRandom()*0.02 SPC getRandom()*0.02 SPC getRandom()*0.02; + %deplObj.setTransform(vectorAdd(pos(%deplObj),%v) SPC rot(%deplObj)); + } + +//////////////////////////Apply settings////////////////////////////// + + // [[Location]]: + + // exact: + + // misc info + addDSurface(%item.surface,%deplObj); + + // [[Settings]]: + + %deplObj.grounded = %grounded; + %deplObj.needsFit = 1; + + // [[Normal Stuff]]: + +// if(%deplObj.getDatablock().rechargeRate) +// %deplObj.setRechargeRate(%deplObj.getDatablock().rechargeRate); + + // set team, owner, and handle + %deplObj.team = %plyr.client.team; + %deplObj.setOwner(%plyr); + + // set power frequency + %deplObj.powerFreq = %plyr.powerFreq; + + // set the sensor group if it needs one + if (%deplObj.getTarget() != -1) + setTargetSensorGroup(%deplObj.getTarget(), %plyr.client.team); + + // place the deployable in the MissionCleanup/Deployables group (AI reasons) + addToDeployGroup(%deplObj); + + //let the AI know as well... + AIDeployObject(%plyr.client, %deplObj); + + // play the deploy sound + serverPlay3D(%item.deploySound, %deplObj.getTransform()); + + // increment the team count for this deployed object + $TeamDeployedCount[%plyr.team, %item.item]++; + + %deplObj.deploy(); + + // Power object + checkPowerObject(%deplObj); + + return %deplObj; +} + +function DeployedwWall::onDestroyed(%this, %obj, %prevState) { + if (%obj.isRemoved) + return; + %obj.isRemoved = true; + Parent::onDestroyed(%this, %obj, %prevState); + $TeamDeployedCount[%obj.team, wwallDeployable]--; + remDSurface(%obj); + %obj.schedule(500, "delete"); + cascade(%obj); + fireBallExplode(%obj,1); +} + +function wWallDeployableImage::onMount(%data, %obj, %node) { + %obj.hasWalk = true; // set for wwallcheck + %obj.packSet = 0; + displayPowerFreq(%obj); +} + +function wWallDeployableImage::onUnmount(%data, %obj, %node) { + %obj.packSet = 0; + %obj.hasWalk = ""; +} diff --git a/scripts/packs/cratepack.cs b/scripts/packs/cratepack.cs new file mode 100644 index 0000000..d6566db --- /dev/null +++ b/scripts/packs/cratepack.cs @@ -0,0 +1,248 @@ +//--------------------------------------------------------- +// Deployable Crates +//--------------------------------------------------------- + +datablock StaticShapeData(DeployedCrate) : StaticShapeDamageProfile { + className = "crate"; + shapeFile = "stackable3s.dts"; + + maxDamage = 0.5; + destroyedLevel = 0.5; + disabledLevel = 0.3; + + explosion = HandGrenadeExplosion; + expDmgRadius = 1.0; + expDamage = 0.05; + expImpulse = 200; + + dynamicType = $TypeMasks::StaticShapeObjectType; + deployedObject = true; + cmdCategory = "DSupport"; + cmdIcon = CMDSensorIcon; + cmdMiniIconName = "commander/MiniIcons/com_deploymotionsensor"; + targetNameTag = 'Deployed Crate'; + deployAmbientThread = true; + debrisShapeName = "debris_generic_small.dts"; + debris = DeployableDebris; + heatSignature = 0; + needsPower = true; +}; + +datablock StaticShapeData(DeployedCrate0) : DeployedCrate { + shapeFile = "stackable1s.dts"; +}; + +datablock StaticShapeData(DeployedCrate1) : DeployedCrate { + shapeFile = "stackable1m.dts"; +}; + +datablock StaticShapeData(DeployedCrate2) : DeployedCrate { + shapeFile = "stackable1l.dts"; +}; + +datablock StaticShapeData(DeployedCrate3) : DeployedCrate { + shapeFile = "stackable2s.dts"; +}; + +datablock StaticShapeData(DeployedCrate4) : DeployedCrate { + shapeFile = "stackable2m.dts"; +}; + +datablock StaticShapeData(DeployedCrate5) : DeployedCrate { + shapeFile = "stackable2l.dts"; +}; + +datablock StaticShapeData(DeployedCrate6) : DeployedCrate { + shapeFile = "stackable3s.dts"; +}; + +datablock StaticShapeData(DeployedCrate7) : DeployedCrate { + shapeFile = "stackable3m.dts"; +}; + +datablock StaticShapeData(DeployedCrate8) : DeployedCrate { + shapeFile = "stackable3l.dts"; +}; + +datablock StaticShapeData(DeployedCrate9) : DeployedCrate { + shapeFile = "stackable4m.dts"; +}; + +datablock StaticShapeData(DeployedCrate10) : DeployedCrate { + shapeFile = "stackable4l.dts"; +}; + +datablock StaticShapeData(DeployedCrate11) : DeployedCrate { + shapeFile = "stackable5m.dts"; +}; + +datablock StaticShapeData(DeployedCrate12) : DeployedCrate { + shapeFile = "stackable5l.dts"; +}; + +datablock ShapeBaseImageData(CrateDeployableImage) { + mass = 1; + emap = true; + shapeFile = "stackable1s.dts"; + item = CrateDeployable; + mountPoint = 1; + offset = "0 0 0"; + deployed = DeployedCrate; + heatSignature = 0; + + stateName[0] = "Idle"; + stateTransitionOnTriggerDown[0] = "Activate"; + + stateName[1] = "Activate"; + stateScript[1] = "onActivate"; + stateTransitionOnTriggerUp[1] = "Idle"; + + isLarge = true; + maxDepSlope = 360; + deploySound = ItemPickupSound; + + minDeployDis = 0.5; + maxDeployDis = 50.0; +}; + +datablock ItemData(CrateDeployable) { + className = Pack; + catagory = "Deployables"; + shapeFile = "stackable1s.dts"; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 1; + rotate = true; + image = "CrateDeployableImage"; + pickUpName = "a crate pack"; + heatSignature = 0; + emap = true; + }; + +function CrateDeployableImage::testObjectTooClose(%item) { + return ""; +} + +function CrateDeployableImage::testNoTerrainFound(%item) { + // don't check this for non-Landspike turret deployables +} + +function CrateDeployable::onPickup(%this, %obj, %shape, %amount) { + // created to prevent console errors +} + +function CrateDeployableImage::onDeploy(%item, %plyr, %slot) { + %className = "StaticShape"; + + %playerVector = vectorNormalize(-1 * getWord(%plyr.getEyeVector(),1) SPC getWord(%plyr.getEyeVector(),0) SPC "0"); + %item.surfaceNrm2 = %playerVector; + %rot = fullRot(%item.surfaceNrm,%item.surfaceNrm2); + + %deplObj = new (%className)() { + dataBlock = %item.deployed @ %plyr.packSet; + }; + + // set orientation + %deplObj.setTransform(%item.surfacePt SPC %rot); + + // set the recharge rate right away + if (%deplObj.getDatablock().rechargeRate) + %deplObj.setRechargeRate(%deplObj.getDatablock().rechargeRate); + + // set team, owner, and handle + %deplObj.team = %plyr.client.Team; + %deplObj.setOwner(%plyr); + + // place the deployable in the MissionCleanup/Deployables group (AI reasons) + addToDeployGroup(%deplObj); + + //let the AI know as well... + AIDeployObject(%plyr.client, %deplObj); + + // play the deploy sound + serverPlay3D(%item.deploySound, %deplObj.getTransform()); + + // increment the team count for this deployed object + $TeamDeployedCount[%plyr.team, %item.item]++; + + addDSurface(%item.surface,%deplObj); + + // take the deployable off the player's back and out of inventory + %plyr.unmountImage(%slot); + %plyr.decInventory(%item.item, 1); + + return %deplObj; +} + +function DeployedCrate::onDestroyed(%this,%obj,%prevState) { + if (%obj.isRemoved) + return; + %obj.isRemoved = true; + Parent::onDestroyed(%this,%obj,%prevState); + $TeamDeployedCount[%obj.team, CrateDeployable]--; + remDSurface(%obj); + %obj.schedule(500, "delete"); +} + +function CrateDeployableImage::onMount(%data, %obj, %node) { + %obj.hasCrate = true; // set for cratecheck + %obj.packSet = 0; +} + +function CrateDeployableImage::onUnmount(%data, %obj, %node) { + %obj.hasCrate = ""; + %obj.packSet = 0; +} + +function DeployedCrate0::onDestroyed(%this,%obj,%prevState) { + DeployedCrate::onDestroyed(%this,%obj,%prevState); +} + +function DeployedCrate1::onDestroyed(%this,%obj,%prevState) { + DeployedCrate::onDestroyed(%this,%obj,%prevState); +} + +function DeployedCrate2::onDestroyed(%this,%obj,%prevState) { + DeployedCrate::onDestroyed(%this,%obj,%prevState); +} + +function DeployedCrate3::onDestroyed(%this,%obj,%prevState) { + DeployedCrate::onDestroyed(%this,%obj,%prevState); +} + +function DeployedCrate4::onDestroyed(%this,%obj,%prevState) { + DeployedCrate::onDestroyed(%this,%obj,%prevState); +} + +function DeployedCrate5::onDestroyed(%this,%obj,%prevState) { + DeployedCrate::onDestroyed(%this,%obj,%prevState); +} + +function DeployedCrate6::onDestroyed(%this,%obj,%prevState) { + DeployedCrate::onDestroyed(%this,%obj,%prevState); +} + +function DeployedCrate7::onDestroyed(%this,%obj,%prevState) { + DeployedCrate::onDestroyed(%this,%obj,%prevState); +} + +function DeployedCrate8::onDestroyed(%this,%obj,%prevState) { + DeployedCrate::onDestroyed(%this,%obj,%prevState); +} + +function DeployedCrate9::onDestroyed(%this,%obj,%prevState) { + DeployedCrate::onDestroyed(%this,%obj,%prevState); +} + +function DeployedCrate10::onDestroyed(%this,%obj,%prevState) { + DeployedCrate::onDestroyed(%this,%obj,%prevState); +} + +function DeployedCrate11::onDestroyed(%this,%obj,%prevState) { + DeployedCrate::onDestroyed(%this,%obj,%prevState); +} + +function DeployedCrate12::onDestroyed(%this,%obj,%prevState) { + DeployedCrate::onDestroyed(%this,%obj,%prevState); +} diff --git a/scripts/packs/deconExamples.cs b/scripts/packs/deconExamples.cs new file mode 100644 index 0000000..9939dbf --- /dev/null +++ b/scripts/packs/deconExamples.cs @@ -0,0 +1,51 @@ +//------------------------------------------------ +// Examples of item specific disassemble. +//================================================ +// ---------------- +// 1. ONE +// ================ +function TelePadDeployedBase::disassemble(%data, %plyr, %hTgt) +{ + %teleteam = %hTgt.team; + if(%obj.Hacked) // is it hacked currently? + { + %teleteam = %hTgt.OldTeam; + echo("hacked!"); + } + + // dising a telepad makes it yours, remove from the other teams list + if($TeamDeployedCount[%teleteam, TelePadPack] > 0) // this wasnt the last + { + if($firstPad[%teleteam] == %hTgt) // the first was disassembled + { + echo("first pad disassembled"); + $firstPad[%teleteam] = %ohTgtbj.nextPad; // make the second one the first + %hTgt.prevPad = -1; + %hTgt.nextPad = %obj; + } + else + { + %lastPad = $firstPad[%teleteam]; + %hTgt.prevPad.nextPad = %hTgt.nextPad; + %hTgt.nextPad.prevPad = %hTgt.prevPad; + } + + } + else // last one + { + $firstPad[%teleteam] = ""; // remove it + } + + %hTgt.shield.delete(); +} + +// -------------- +// 2. Two +// ============== + +function MobileBaseVehicle::disassemble(%data, %plyr, %hTgt) +{ + %mpbpos = %hTgt.gettransform(); + %hTgt.delete(); + teleporteffect(posfromtransform(%mpbpos)); +} diff --git a/scripts/packs/decorationpack.cs b/scripts/packs/decorationpack.cs new file mode 100644 index 0000000..f110690 --- /dev/null +++ b/scripts/packs/decorationpack.cs @@ -0,0 +1,376 @@ +//--------------------------------------------------------- +// Deployable Decoration +//--------------------------------------------------------- + +datablock StaticShapeData(DeployedDecoration) : StaticShapeDamageProfile { + className = "decoration"; + shapeFile = "banner_unity.dts"; + + maxDamage = 0.5; + destroyedLevel = 0.5; + disabledLevel = 0.3; + + explosion = HandGrenadeExplosion; + expDmgRadius = 1.0; + expDamage = 0.05; + expImpulse = 200; + + dynamicType = $TypeMasks::StaticShapeObjectType; + deployedObject = true; + cmdCategory = "DSupport"; + cmdIcon = CMDSensorIcon; + cmdMiniIconName = "commander/MiniIcons/com_deploymotionsensor"; + targetNameTag = 'Deployed Decoration'; + deployAmbientThread = true; + debrisShapeName = "debris_generic_small.dts"; + debris = DeployableDebris; + heatSignature = 0; +}; + +datablock StaticShapeData(DeployedDecoration0) : DeployedDecoration { + shapeFile = "banner_unity.dts"; +}; + +datablock StaticShapeData(DeployedDecoration1) : DeployedDecoration { + shapeFile = "banner_strength.dts"; +}; + +datablock StaticShapeData(DeployedDecoration2) : DeployedDecoration { + shapeFile = "banner_honor.dts"; +}; + +datablock StaticShapeData(DeployedDecoration3) : DeployedDecoration { + shapeFile = "light_male_dead.dts"; +}; + +datablock StaticShapeData(DeployedDecoration4) : DeployedDecoration { + shapeFile = "medium_male_dead.dts"; +}; + +datablock StaticShapeData(DeployedDecoration5) : DeployedDecoration { + shapeFile = "heavy_male_dead.dts"; +}; + +datablock StaticShapeData(DeployedDecoration6) : DeployedDecoration { + shapeFile = "statue_base.dts"; +}; + +datablock StaticShapeData(DeployedDecoration7) : DeployedDecoration { + shapeFile = "statue_lmale.dts"; +}; + +datablock StaticShapeData(DeployedDecoration8) : DeployedDecoration { + shapeFile = "statue_lfemale.dts"; +}; + +datablock StaticShapeData(DeployedDecoration9) : DeployedDecoration { + shapeFile = "statue_hmale.dts"; +}; + +datablock StaticShapeData(DeployedDecoration10) : DeployedDecoration { + shapeFile = "vehicle_grav_tank_wreck.dts"; +}; + +datablock StaticShapeData(DeployedDecoration11) : DeployedDecoration { + shapeFile = "vehicle_air_scout_wreck.dts"; +}; + +datablock StaticShapeData(DeployedDecoration12) : DeployedDecoration { + shapeFile = "billboard_1.dts"; +}; + +datablock StaticShapeData(DeployedDecoration13) : DeployedDecoration { + shapeFile = "billboard_2.dts"; +}; + +datablock StaticShapeData(DeployedDecoration14) : DeployedDecoration { + shapeFile = "billboard_3.dts"; +}; + +datablock StaticShapeData(DeployedDecoration15) : DeployedDecoration { + shapeFile = "billboard_4.dts"; +}; + +datablock ShapeBaseImageData(DecorationDeployableImage) { + mass = 1; + emap = true; + shapeFile = "statue_lfemale.dts"; // "stackable1s.dts"; + item = DecorationDeployable; + mountPoint = 1; + offset = "0 -0.6 -1.9"; + rotation = "0 0.1 1 180"; + deployed = DeployedDecoration; + heatSignature = 0; + + stateName[0] = "Idle"; + stateTransitionOnTriggerDown[0] = "Activate"; + + stateName[1] = "Activate"; + stateScript[1] = "onActivate"; + stateTransitionOnTriggerUp[1] = "Idle"; + + isLarge = true; + maxDepSlope = 360; + deploySound = ItemPickupSound; + + minDeployDis = 0.5; + maxDeployDis = 50.0; +}; + +datablock ItemData(DecorationDeployable) { + className = Pack; + catagory = "Deployables"; + shapeFile = "stackable1s.dts"; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 1; + rotate = true; + image = "DecorationDeployableImage"; + pickUpName = "a decoration pack"; + heatSignature = 0; + emap = true; + }; + +function DecorationDeployableImage::testObjectTooClose(%item) { + return ""; +} + +function DecorationDeployableImage::testNoTerrainFound(%item) { + // don't check this for non-Landspike turret deployables +} + +function DecorationDeployable::onPickup(%this, %obj, %shape, %amount) { + // created to prevent console errors +} + +function DecorationDeployableImage::onDeploy(%item, %plyr, %slot) { + %className = "StaticShape"; + + %playerVector = vectorNormalize(-1 * getWord(%plyr.getEyeVector(),1) SPC getWord(%plyr.getEyeVector(),0) SPC "0"); + + if (vAbs(floorVec(%item.surfaceNrm,100)) $= "0 0 1") { + if (%plyr.packSet == 3 || %plyr.packSet == 5) + %item.surfaceNrm2 = vectorScale(%playerVector,-1); + else + %item.surfaceNrm2 = %playerVector; + } + else { + if (%plyr.packSet < 3) + %item.surfaceNrm2 = vectorNormalize(vectorCross(%item.surfaceNrm,"0 0 1")); + else { + %item.surfaceNrm2 = %playerVector; + if (%plyr.packSet == 3 || %plyr.packSet == 5) + %item.surfaceNrm2 = vectorScale(%item.surfaceNrm2,-1); + } + } + if (%item.surface.needsFit == 1) { + if (%plyr.packSet > 5 && %plyr.packSet < 10 && %item.surface.getDataBlock().getName() $= "DeployedDecoration6") { + %item.surfaceNrm2 = vectorCross(%item.surfaceNrm,realVec(%item.surface,"0 -1 0")); + } + } + %item.surfaceNrm3 = vectorCross(%item.surfaceNrm,%item.surfaceNrm2); + + + %rot = fullRot(%item.surfaceNrm,%item.surfaceNrm2); + + %deplObj = new (%className)() { + dataBlock = %item.deployed @ %plyr.packSet; + }; + + if (%plyr.packSet < 3) { + %surfacePt2 = %item.surfacePt; + %rot2 = %rot; + %item.surfaceNrm2 = vectorScale(%item.surfaceNrm2,-1); + %item.surfacePt = vectorAdd(%item.surfacePt,vectorScale(%item.surfaceNrm3,2.80)); + %item.surfacePt = vectorAdd(%item.surfacePt,vectorScale(%item.surfaceNrm,0.25)); + %rot = rotAdd(%rot,"1 0 0" SPC $Pi / 2); + %rot = rotAdd(%rot,"0 1 0" SPC $Pi); + %deplObj.lTarget = new StaticShape () { + datablock = DeployedLTarget; + scale = 2.5/4 SPC 5/3 SPC 0.15 * 2; + }; + %deplObj.lTarget.setTransform(%surfacePt2 SPC %rot2); + %deplObj.lTarget.lMain = %deplObj; + } + + if (%plyr.packSet > 2 && %plyr.packSet < 6) { + %surfacePt2 = vectorAdd(%item.surfacePt,vectorScale(%item.surfaceNrm,0.2)); + %rot2 = %rot; + if (%plyr.packSet == 3) { + %surfacePt2 = vectorAdd(%surfacePt2,vectorScale(%item.surfaceNrm2,-0.14)); + %surfacePt2 = vectorAdd(%surfacePt2,vectorScale(%item.surfaceNrm3,0.51)); + } + else if (%plyr.packSet == 4) { + %surfacePt2 = vectorAdd(%surfacePt2,vectorScale(%item.surfaceNrm2,0.25)); + %surfacePt2 = vectorAdd(%surfacePt2,vectorScale(%item.surfaceNrm3,-0.4)); + } + else if (%plyr.packSet == 5) { + %surfacePt2 = vectorAdd(%surfacePt2,vectorScale(%item.surfaceNrm2,0.05)); + %surfacePt2 = vectorAdd(%surfacePt2,vectorScale(%item.surfaceNrm3,0.4)); + %rot = rotAdd(%rot,"0 0 -1" SPC $Pi / 4); + } + %deplObj.lTarget = new StaticShape () { + datablock = DeployedLTarget; + scale = 0.4/4 SPC 0.5/3 SPC 0.05 * 2; + }; + %deplObj.lTarget.setTransform(%surfacePt2 SPC %rot2); + %deplObj.lTarget.lMain = %deplObj; + } + + if (%plyr.packSet == 11) + %item.surfacePt = vectorAdd(%item.surfacePt,vectorScale(%item.surfaceNrm,-2)); + + if (%plyr.packSet > 11 && %plyr.packSet < 16) { + %surfacePt2 = %item.surfacePt; + %rot2 = %rot; + %item.surfaceNrm2 = vectorScale(%item.surfaceNrm2,-1); + %item.surfacePt = vectorAdd(%item.surfacePt,vectorScale(%item.surfaceNrm,10.9)); + %surfacePt2 = vectorAdd(%surfacePt2,vectorScale(%item.surfaceNrm,34)); + %surfacePt2 = vectorAdd(%surfacePt2,vectorScale(%item.surfaceNrm3,-1)); + %rot2 = rotAdd(%rot,"1 0 0" SPC $Pi / 2); + %deplObj.lTarget = new StaticShape () { + datablock = DeployedLTarget; + scale = 74/4 SPC 49/3 SPC 4; + }; + %deplObj.lTarget.setTransform(%surfacePt2 SPC %rot2); + %deplObj.lTarget.lMain = %deplObj; + } + + // set orientation + %deplObj.setTransform(%item.surfacePt SPC %rot); + + // set the recharge rate right away + if (%deplObj.getDatablock().rechargeRate) { + %deplObj.setRechargeRate(%deplObj.getDatablock().rechargeRate); + %deplObj.lTarget.setRechargeRate(%deplObj.getDatablock().rechargeRate); + } + + // [[Settings]]: + %deplObj.needsFit = 1; + + // set team, owner, and handle + %deplObj.team = %plyr.client.Team; + %deplObj.setOwner(%plyr); + if (%deplObj.lTarget) { + %deplObj.lTarget.team = %plyr.client.Team; + %deplObj.lTarget.setOwner(%plyr); + } + + // place the deployable in the MissionCleanup/Deployables group (AI reasons) + addToDeployGroup(%deplObj); + if (%deplObj.lTarget) + addToDeployGroup(%deplObj.lTarget); + + //let the AI know as well... + AIDeployObject(%plyr.client,%deplObj); + if (%deplObj.lTarget) + AIDeployObject(%plyr.client,%deplObj.lTarget); + + // play the deploy sound + serverPlay3D(%item.deploySound, %deplObj.getTransform()); + + // increment the team count for this deployed object + $TeamDeployedCount[%plyr.team, %item.item]++; + + addDSurface(%item.surface,%deplObj); + if (%deplObj.lTarget) + addDSurface(%deplObj,%deplObj.lTarget); + + // take the deployable off the player's back and out of inventory + %plyr.unmountImage(%slot); + %plyr.decInventory(%item.item, 1); + + return %deplObj; +} + +function DeployedDecoration::onDestroyed(%this,%obj,%prevState) { + if (%obj.isRemoved) + return; + %obj.isRemoved = true; + Parent::onDestroyed(%this,%obj,%prevState); + $TeamDeployedCount[%obj.team, DecorationDeployable]--; + remDSurface(%obj); + %obj.schedule(500, "delete"); + if (isObject(%obj.lTarget)) + %obj.lTarget.schedule(500, "delete"); + fireBallExplode(%obj,1); +} + +function DecorationDeployableImage::onMount(%data, %obj, %node) { + %obj.hasDecoration = true; // set for decorationcheck + %obj.packSet = 0; +} + +function DecorationDeployableImage::onUnmount(%data, %obj, %node) { + %obj.hasDecoration = ""; + %obj.packSet = 0; +} + +function DeployedDecoration0::onDestroyed(%this,%obj,%prevState) { + DeployedDecoration::onDestroyed(%this,%obj,%prevState); +} + +function DeployedDecoration1::onDestroyed(%this,%obj,%prevState) { + DeployedDecoration::onDestroyed(%this,%obj,%prevState); +} + +function DeployedDecoration2::onDestroyed(%this,%obj,%prevState) { + DeployedDecoration::onDestroyed(%this,%obj,%prevState); +} + +function DeployedDecoration3::onDestroyed(%this,%obj,%prevState) { + DeployedDecoration::onDestroyed(%this,%obj,%prevState); +} + +function DeployedDecoration4::onDestroyed(%this,%obj,%prevState) { + DeployedDecoration::onDestroyed(%this,%obj,%prevState); +} + +function DeployedDecoration5::onDestroyed(%this,%obj,%prevState) { + DeployedDecoration::onDestroyed(%this,%obj,%prevState); +} + +function DeployedDecoration6::onDestroyed(%this,%obj,%prevState) { + DeployedDecoration::onDestroyed(%this,%obj,%prevState); +} + +function DeployedDecoration7::onDestroyed(%this,%obj,%prevState) { + DeployedDecoration::onDestroyed(%this,%obj,%prevState); +} + +function DeployedDecoration8::onDestroyed(%this,%obj,%prevState) { + DeployedDecoration::onDestroyed(%this,%obj,%prevState); +} + +function DeployedDecoration9::onDestroyed(%this,%obj,%prevState) { + DeployedDecoration::onDestroyed(%this,%obj,%prevState); +} + +function DeployedDecoration10::onDestroyed(%this,%obj,%prevState) { + DeployedDecoration::onDestroyed(%this,%obj,%prevState); +} + +function DeployedDecoration11::onDestroyed(%this,%obj,%prevState) { + DeployedDecoration::onDestroyed(%this,%obj,%prevState); +} + +function DeployedDecoration12::onDestroyed(%this,%obj,%prevState) { + DeployedDecoration::onDestroyed(%this,%obj,%prevState); +} + +function DeployedDecoration13::onDestroyed(%this,%obj,%prevState) { + DeployedDecoration::onDestroyed(%this,%obj,%prevState); +} + +function DeployedDecoration14::onDestroyed(%this,%obj,%prevState) { + DeployedDecoration::onDestroyed(%this,%obj,%prevState); +} + +function DeployedDecoration15::onDestroyed(%this,%obj,%prevState) { + DeployedDecoration::onDestroyed(%this,%obj,%prevState); +} + +function DeployedDecoration16::onDestroyed(%this,%obj,%prevState) { + DeployedDecoration::onDestroyed(%this,%obj,%prevState); +} diff --git a/scripts/packs/discturret.cs b/scripts/packs/discturret.cs new file mode 100644 index 0000000..b0e2769 --- /dev/null +++ b/scripts/packs/discturret.cs @@ -0,0 +1,257 @@ +//-------------------------------------------------------------------------- +// Datablocks Disc turret +//-------------------------------------- + +datablock SensorData(DiscTurretSensor) +{ +detects = true; +detectsUsingLOS = true; +detectsPassiveJammed = false; +detectsActiveJammed = false; +detectsCloaked = false; +detectionPings = true; +detectRadius = 60; +}; + +datablock TurretData(DiscTurretDeployed) : TurretDamageProfile +{ +className = DeployedTurret; +shapeFile = "turret_outdoor_deploy.dts"; +mass = 1; +maxDamage = 1.5; //was 0.5; +destroyedLevel = 0.5; +disabledLevel = 0.21; +explosion = SmallTurretExplosion; +expDmgRadius = 5.0; +expDamage = 0.25; +expImpulse = 500.0; +repairRate = 0; +heatSignature = 0.0; +deployedObject = true; +thetaMin = 5; +thetaMax = 145; +thetaNull = 90; +primaryAxis = zaxis; +isShielded = true; +energyPerDamagePoint = 30; +maxEnergy = 50; +rechargeRate = 0.20; //was 0.10; +barrel = DeployableDiscTurretBarrel; +canControl = true; +cmdCategory = "DTactical"; +cmdIcon = CMDTurretIcon; +cmdMiniIconName = "commander/MiniIcons/com_turret_grey"; +targetNameTag = 'Disc'; +targetTypeTag = 'Turret'; +sensorData = DiscTurretSensor; +sensorRadius = DiscTurretSensor.detectRadius; +sensorColor = "191 0 226"; +firstPersonOnly = true; +renderWhenDestroyed = true; +debrisShapeName = "debris_generic_small.dts"; +debris = TurretDebrisSmall; +}; + +datablock TurretImageData(DeployableDiscTurretBarrel) +{ +shapeFile = "weapon_disc.dts"; +item = DiscTurretBarrel; +rotation = "0 1 0 90"; +//rotation = "0 0 0 0"; +offset = "0 0 0"; +projectile = DiscProjectile; +projectileType = LinearProjectile; +usesEnergy = true; +fireEnergy = 10; ///was 20 +minEnergy = 10; ///was 20 +lightType = "WeaponFireLight"; +lightColor = "0.25 0.15 0.15 1.0"; +lightTime = "1000"; +lightRadius = "2"; +muzzleFlash = IndoorTurretMuzzleFlash; + +// Turret parameters +activationMS = 150; +deactivateDelayMS = 300; +thinkTimeMS = 150; +degPerSecTheta = 580; +degPerSecPhi = 960; +attackRadius = 150; //100 + +// State Data +stateName[0] = "Preactivate"; +stateTransitionOnLoaded[0] = "Activate"; +stateTransitionOnNoAmmo[0] = "NoAmmo"; + +stateName[1] = "Activate"; +stateTransitionOnTimeout[1] = "Ready"; +stateTimeoutValue[1] = 0.05; +stateSequence[1] = "Activated"; +stateSound[1] = DiscSwitchSound; + +stateName[2] = "Ready"; +stateTransitionOnNoAmmo[2] = "NoAmmo"; +stateTransitionOnTriggerDown[2] = "Fire"; +stateSequence[2] = "DiscSpin"; +stateSound[2] = DiscLoopSound; + +stateName[3] = "Fire"; +stateTransitionOnTimeout[3] = "Reload"; +stateTimeoutValue[3] = 0.025; +stateFire[3] = true; +stateRecoil[3] = LightRecoil; +stateAllowImageChange[3] = false; +stateSequence[3] = "Fire"; +stateScript[3] = "onFire"; +stateSound[3] = DiscFireSound; + +stateName[4] = "Reload"; +stateTransitionOnNoAmmo[4] = "NoAmmo"; +stateTransitionOnTimeout[4] = "Ready"; +stateTimeoutValue[4] = 0.1; // 0.25 load, 0.25 spinup +stateAllowImageChange[4] = false; +stateSequence[4] = "Reload"; +stateSound[4] = DiscReloadSound; + +stateName[5] = "NoAmmo"; +stateTransitionOnAmmo[5] = "Reload"; +stateSequence[5] = "NoAmmo"; +stateTransitionOnTriggerDown[5] = "DryFire"; + +stateName[6] = "DryFire"; +//stateSound[6] = DiscDryFireSound; +stateTimeoutValue[6] = 0.1; +stateTransitionOnTimeout[6] = "NoAmmo"; + +}; +datablock ShapeBaseImageData(DiscTurretDeployableImage) +{ +mass = 1; +shapeFile = "pack_deploy_turreti.dts"; +item = DiscTurretDeployable; +mountPoint = 1; +offset = "0 0 0"; +deployed = DiscTurretDeployed; +stateName[0] = "Idle"; +stateTransitionOnTriggerDown[0] = "Activate"; + +stateName[1] = "Activate"; +stateScript[1] = "onActivate"; +stateTransitionOnTriggerUp[1] = "Idle"; + +isLarge = true; +emap = true; +maxDepSlope = 360; +deploySound = TurretDeploySound; +minDeployDis = 0.5; +maxDeployDis = 5.0; +}; + +datablock ItemData(DiscTurretDeployable) +{ +className = Pack; +catagory = "Deployables"; +shapeFile = "pack_deploy_turreti.dts"; +mass = 1; +elasticity = 0.2; +friction = 0.6; +pickupRadius = 1; +rotate = false; +image = "DiscTurretDeployableImage"; +pickUpName = "a disc turret pack"; +emap = true; +}; + +//-------------------------------------------------------------------------- +// Functions +//-------------------------------------- + +function DiscTurretDeployableImage::testNoTerrainFound(%item) +{ +// created to prevent console errors +} + +function DiscTurretDeployableImage::testNoInteriorFound(%item) +{ +// created to prevent console errors +} + +function DiscTurretDeployableImage::onDeploy(%item, %plyr, %slot) +{ +%searchRange = 5.0; +%mask = $TypeMasks::TerrainObjectType | $TypeMasks::InteriorObjectType; +%eyeVec = %plyr.getEyeVector(); +%eyeTrans = %plyr.getEyeTransform(); +%eyePos = posFromTransform(%eyeTrans); +%nEyeVec = VectorNormalize(%eyeVec); +%scEyeVec = VectorScale(%nEyeVec, %searchRange); +%eyeEnd = VectorAdd(%eyePos, %scEyeVec); +//%searchResult = containerRayCast(%eyePos, %eyeEnd, %mask, 0); +//if(!%searchResult ) { +//messageClient(%plyr.client, 'MsgBeaconNoSurface', 'c2Cannot place turret. You are too far from surface.'); +//return 0; +//} +%terrPt = %item.surfacept; +%terrNrm = %item.surfacenrm; +%intAngle = getTerrainAngle(%terrNrm); +%rotAxis = vectorNormalize(vectorCross(%terrNrm, "0 0 1")); +if ((getWord(%terrNrm, 2) == 1) || (getWord(%terrNrm, 2) == -1)) +%rotAxis = vectorNormalize(vectorCross(%terrNrm, "0 1 0")); +%rotation = %rotAxis @ " " @ %intAngle; +%plyr.unmountImage(%slot); +%plyr.decInventory(%item.item, 1); + +%deplObj = new Turret() { +dataBlock = %item.deployed; +position = VectorAdd(%terrPt, VectorScale(%terrNrm, 0.03)); +rotation = %rotation; +}; + addDSurface(%item.surface,%deplObj); +%deplObj.setRechargeRate(%deplObj.getDatablock().rechargeRate); +%deplObj.team = %plyr.client.team; + %deplObj.setOwner(%plyr); +%deplObj.setOwnerClient(%plyr.client); +if(%deplObj.getTarget() != -1) +setTargetSensorGroup(%deplObj.getTarget(), %plyr.client.team); + +addToDeployGroup(%deplObj); +AIDeployObject(%plyr.client, %deplObj); +serverPlay3D(%item.deploySound, %deplObj.getTransform()); +$TeamDeployedCount[%plyr.team, %item.item]++; +%deplObj.deploy(); +%deplObj.playThread($AmbientThread, "ambient"); +return %deplObj; +} + +function DiscTurretDeployable::onPickup(%this, %obj, %shape, %amount) +{ +// created to prevent console errors +} + +function DeployableDiscTurretBarrel::onFire( %data, %obj, %slot ) { + %energy = %obj.getEnergyLevel(); + %p = new (LinearProjectile)() { + dataBlock = DiscProjectile; + initialDirection = %obj.getMuzzleVector(%slot); + initialPosition = %obj.getMuzzlePoint(%slot); + sourceObject = %obj; + damageFactor = 1; + sourceSlot = %slot; + }; + %obj.lastProjectile = %p; + MissionCleanup.add(%p); + %obj.setEnergyLevel(%energy - %data.fireEnergy); +} + +function DiscTurretDeployed::onDestroyed(%this, %obj, %prevState) { + if (%obj.isRemoved) + return; + if ($Host::InvincibleDeployables != 1 || %obj.damageFailedDecon) { + %obj.isRemoved = true; + $TeamDeployedCount[%obj.team, DiscTurretDeployable]--; + remDSurface(%obj); + %obj.schedule(500, "delete"); + } + Parent::onDestroyed(%this, %obj, %prevState); +} + diff --git a/scripts/packs/door.cs b/scripts/packs/door.cs new file mode 100644 index 0000000..55f3e32 --- /dev/null +++ b/scripts/packs/door.cs @@ -0,0 +1,330 @@ +//client.player.setInventory(doorDeployable,1,true); +//--------------------------------------------------------- +// Deployable mspine, Code by Parousia +//--------------------------------------------------------- +datablock StaticShapeData(DeployedDoor) : StaticShapeDamageProfile { +className = "door"; +shapeFile = "Pmiscf.dts"; // b or dmiscf.dts, alternate + +maxDamage = 2; +destroyedLevel = 2; +disabledLevel = 1.5; + +isShielded = true; +energyPerDamagePoint = 60; +maxEnergy = 100; +rechargeRate = 0.25; + +explosion = HandGrenadeExplosion; +expDmgRadius = 3.0; +expDamage = 0.1; +expImpulse = 200.0; + +dynamicType = $TypeMasks::StaticShapeObjectType; +deployedObject = true; +cmdCategory = "DSupport"; +cmdIcon = CMDSensorIcon; +cmdMiniIconName = "commander/MiniIcons/com_deploymotionsensor"; +targetNameTag = 'Door'; +deployAmbientThread = true; +debrisShapeName = "debris_generic_small.dts"; +debris = DeployableDebris; +heatSignature = 0; +needsPower = true; +}; + +datablock ShapeBaseImageData(DoorDeployableImage) { +mass = 1; +emap = true; +shapeFile = "stackable1s.dts"; +item = DoorDeployable; +mountPoint = 1; +offset = "0 0 0"; +deployed = DeployedDoor; +heatSignature = 0; + +stateName[0] = "Idle"; +stateTransitionOnTriggerDown[0] = "Activate"; + +stateName[1] = "Activate"; +stateScript[1] = "onActivate"; +stateTransitionOnTriggerUp[1] = "Idle"; + +isLarge = false; +maxDepSlope = 360; +deploySound = ItemPickupSound; + +minDeployDis = 0; +maxDeployDis = 50.0; +}; + +datablock ItemData(DoorDeployable) { +className = Pack; +catagory = "Deployables"; +shapeFile = "stackable1s.dts"; +mass = 1; +elasticity = 0.2; +friction = 0.6; +pickupRadius = 1; +rotate = true; +image = "DoorDeployableImage"; +pickUpName = "a door pack made by Linker"; +heatSignature = 0; +emap = true; +}; + +function DoorDeployableImage::testObjectTooClose(%item) { +return ""; +} + +function DoorDeployableImage::testNoTerrainFound(%item) { +// don't check this for non-Landspike turret deployables +} + +function DoorDeployable::onPickup(%this, %obj, %shape, %amount) { +// created to prevent console errors +} + +function doorDeployableImage::onMount(%data, %obj, %node) { +%obj.hasDoor = true; // set for blastcheck +%obj.packSet = 0; +%obj.expertSet = 3; +displayPowerFreq(%obj); + +} + +function doorDeployableImage::onUnmount(%data, %obj, %node) { +%obj.hasDoor = ""; +%obj.packSet = 0; +%obj.expertSet = 0; +} + +function doorDeployableImage::onDeploy(%item, %plyr, %slot) { + %className = "StaticShape"; + %grounded = 0; + if (%item.surface.getClassName() $= TerrainBlock) + %grounded = 1; + + %playerVector = vectorNormalize(-1 * getWord(%plyr.getEyeVector(),1) SPC getWord(%plyr.getEyeVector(),0) SPC "0"); + + if (%item.surfaceinher == 0) { + if (vAbs(floorVec(%item.surfaceNrm,100)) $= "0 0 1"){ + %item.surfaceNrm2 = %playerVector; + } + else{ + %item.surfaceNrm2 = vectorNormalize(vectorCross(%item.surfaceNrm,"0 0 1")); + } + } + + %rot1 = fullRot(%item.surfaceNrm,%item.surfaceNrm2); + + %scale1 = "0.5 6 160"; + %scale2 = "0.5 8 160"; + %dataBlock = %item.deployed; + + %space = rayDist(%item.surfacePt SPC %item.surfaceNrm,%scale1,$AllObjMask); + if (%space != getWord(%scale1,1)) + %type = true; + %scale1 = getWord(%scale1,0) SPC getWord(%scale1,0) SPC %space; + + + %mCenter = "0 0 -0.5"; + %pad = pad(%item.surfacePt SPC %item.surfaceNrm SPC %item.surfaceNrm2,%scale2,%mCenter); + %scale2 = getWords(%pad,0,2); + %item.surfacePt2 = getWords(%pad,3,5); + + //%vec1 = realVec(getWord(%item.surface,0),%item.surfaceNrm); + //%vec1 = realVec(%pad,%item.surfaceNrm); + %vec1 =validateVal(MatrixMulVector("0 0 0",%item.surfaceNrm)); + + if (!%scaleIsSet){ + %scale1 = vectorMultiply(%scale1,1/4 SPC 1/3 SPC 2); + %scale2 = vectorMultiply(%scale2,1/4 SPC 1/3 SPC 2); + %x = (getWord(%scale2,1)/0.166666)*0.125; + %scale3 = %x SPC 0.166666 SPC getWord(%scale1,2); + } + + + + %dir1 = VectorNormalize(vectorSub(%item.surfacePt,%item.surfacePt2)); + %adjust1 = vectorNormalize(vectorProject(%dir1,vectorCross(%item.surfaceNrm,%item.surfaceNrm2))); + %offset1 = -0.5; + %adjust1 = vectorScale(%adjust1,-0.5 * %offset1); + + %deplObj = new (%className)() { + dataBlock = %dataBlock; + scale = %scale3; + }; + %deplObj.closedscale = %scale3; + %deplObj.openedscale = getwords(%scale3,0,1) SPC 0.1; +//////////////////////////Apply settings////////////////////////////// + + // exact: + //%deplObj.setTransform(%item.surfacePt SPC %rot1); + %deplObj.setTransform(vectorAdd(VectorAdd(%item.surfacePt2, VectorScale(%vec1,getword(%scale3,2)/-4)),%adjust1) SPC %rot1); + + // misc info + addDSurface(%item.surface,%deplObj); + // [[Settings]]: + + %deplObj.grounded = %grounded; + %deplObj.needsFit = 1; + %deplObj.isdoor = 1; + // [[Normal Stuff]]: + + // set team, owner, and handle + %deplObj.team = %plyr.client.team; + %deplObj.setOwner(%plyr); + + // set power frequency + %deplObj.powerFreq = %plyr.powerFreq; + + // set the sensor group if it needs one + if (%deplObj.getTarget() != -1) + setTargetSensorGroup(%deplObj.getTarget(), %plyr.client.team); + + // place the deployable in the MissionCleanup/Deployables group (AI reasons) + addToDeployGroup(%deplObj); + + //let the AI know as well... + AIDeployObject(%plyr.client, %deplObj); + + // play the deploy sound + serverPlay3D(%item.deploySound, %deplObj.getTransform()); + + // increment the team count for this deployed object + $TeamDeployedCount[%plyr.team, %item.item]++; + + %deplObj.deploy(); + +// Power object +checkPowerObject(%deplObj); +%deplobj.timeout=getWord($expertSetting["Door",%plyr.expertSet],0); +%deplobj.hasslided=0; + +if (%plyr.packset==0) +%deplobj.toggletype=0; + +if (%plyr.packset==1) +%deplobj.toggletype=1; + +if (%plyr.packset==2) { +%deplobj.toggletype=0; +%deplobj.powercontrol=1; //staticshape.cs function StaticShapeData::onGainPowerEnabled |and| function StaticShapeData::onLosePowerDisabled +} //for power togle code + +if (%plyr.packset==3) { +%deplobj.toggletype=1; +%deplobj.powercontrol=1; +} +//collision door +if (%plyr.packset==4){ +%deplobj.toggletype=0; +%deplobj.Collision = true; +%deplobj.lv =0; +} +//owner door +if (%plyr.packset==5){ +%deplobj.toggletype=0; +%deplobj.Collision = true; +%deplobj.lv =1; +} +//admin door +if (%plyr.packset==6){ +%deplobj.toggletype=0; +%deplobj.Collision = true; +%deplobj.lv =2; +} +if (%plyr.packset==7){ +%deplobj.toggletype=0; +%deplobj.Collision = true; +%deplobj.lv =0; +%deplobj.canlock = true; +} +%deplobj.canmove = true; + return %deplObj; +} + +function Deployeddoor::onDestroyed(%this, %obj, %prevState) { + if (%obj.isRemoved) + return; + %obj.isRemoved = true; + Parent::onDestroyed(%this, %obj, %prevState); + $TeamDeployedCount[%obj.team, TdoorDeployable]--; + remDSurface(%obj); + %obj.schedule(500,"delete"); + cascade(%obj); + fireBallExplode(%obj,1); +} + +function Deployeddoor::disassemble(%data,%plyr,%hTgt) { + disassemble(%data,%plyr,%hTgt); +} + +function doorDeployableImage::onMount(%data,%obj,%node) { + %obj.hasdoor = true; // set for mspinecheck + %obj.packSet = 0; + %obj.expertSet = 0; + displayPowerFreq(%obj); +} + +function doorDeployableImage::onUnmount(%data,%obj,%node) { + %obj.hasdoor = ""; + %obj.packSet = 0; + %obj.expertSet = 0; +} +//////////////////// +//////////////////// +function open(%obj){ +if (!isObject(%obj)) + return; +if (%obj.canmove == true){ + %obj.moving = "open"; //wat direction its moving + %obj.prevscale =%obj.scale; //scale befor this change + %obj.closedscale=%obj.scale;//scale it is while fully closed + %obj.canmove = false; +} + +if (getWord(%obj.scale,2)<0.3){ + %obj.issliding = 0; + %obj.scale = getWord(%obj.scale,0) SPC getWord(%obj.scale,1) SPC 0.1; + %obj.settransform(%obj.gettransform()); + %obj.state = "opened"; //last state used for savebuilding + %obj.openedscale = %obj.scale; + if (%obj.toggletype ==0) + schedule(%obj.timeout*1000,0,"close",%obj,1); + else + %obj.canmove = true; + return; + } +%obj.scale = getWord(%obj.scale,0) SPC getWord(%obj.scale,1) SPC getWord(%obj.prevscale,2)-0.4; +%obj.settransform(%obj.gettransform()); +%obj.prevscale=%obj.scale; +schedule(40,0,"open",%obj); +} +///////////////////// +///////////////////// +function close(%obj,%timeout){ +if (!isObject(%obj)) + return; +if (%obj.canmove == true){ + %obj.moving = "close"; //wat direction its moving + %obj.prevscale =%obj.scale; //scale befor this change + %obj.openedscale=%obj.scale;//scale it is while fully opened + %obj.canmove = false; +} + +if (getWord(%obj.scale,2)>getWord(%obj.closedscale,2)-0.2){ + %obj.issliding = 0; + %obj.scale =getWord(%obj.scale,0) SPC getWord(%obj.scale,1) SPC getWord(%obj.closedscale,2); + %obj.settransform(%obj.gettransform()); + %obj.state = "closed"; //last state used for savebuilding + %obj.closedscale = %obj.scale; + %obj.canmove = true; + return; + } +%obj.scale = getWord(%obj.scale,0) SPC getWord(%obj.scale,1) SPC getWord(%obj.prevscale,2)+0.4; +%obj.settransform(%obj.gettransform()); +%obj.prevscale=%obj.scale; +schedule(40,0,"close",%obj); +} diff --git a/scripts/packs/doorbu.cs b/scripts/packs/doorbu.cs new file mode 100644 index 0000000..1061e0a --- /dev/null +++ b/scripts/packs/doorbu.cs @@ -0,0 +1,322 @@ +//--------------------------------------------------------- +// Deployable door, Code by Linker +// Modified by Electricutioner/Thyth to prevent server crash exploit. +//--------------------------------------------------------- + +datablock EffectProfile(DoorCloseEffect) +{ +effectname = "weapons/missile_fire"; +minDistance = 0.5; +maxDistance = 20.0; +}; + +datablock AudioProfile(DoorCloseSound) +{ +filename = "fx/vehicles/tank_mortar_fire.wav"; +description = AudioDefault3d; +preload = true; +effect = DoorCloseEffect; +}; + + +datablock StaticShapeData(DeployedDoor) : StaticShapeDamageProfile { +className = "door"; +shapeFile = "Pmiscf.dts"; // b or dmiscf.dts, alternate + +maxDamage = 2; +destroyedLevel = 2; +disabledLevel = 1.5; + +isShielded = true; +energyPerDamagePoint = 60; +maxEnergy = 100; +rechargeRate = 0.25; + +explosion = HandGrenadeExplosion; +expDmgRadius = 3.0; +expDamage = 0.1; +expImpulse = 200.0; + +dynamicType = $TypeMasks::StaticShapeObjectType; +deployedObject = true; +cmdCategory = "DSupport"; +cmdIcon = CMDSensorIcon; +cmdMiniIconName = "commander/MiniIcons/com_deploymotionsensor"; +targetNameTag = 'Door'; +deployAmbientThread = true; +debrisShapeName = "debris_generic_small.dts"; +debris = DeployableDebris; +heatSignature = 0; +needsPower = true; +}; + +datablock ShapeBaseImageData(DoorDeployableImage) { +mass = 1; +emap = true; +shapeFile = "stackable1s.dts"; +item = DoorDeployable; +mountPoint = 1; +offset = "0 0 0"; +deployed = DeployedDoor; +heatSignature = 0; + +stateName[0] = "Idle"; +stateTransitionOnTriggerDown[0] = "Activate"; + +stateName[1] = "Activate"; +stateScript[1] = "onActivate"; +stateTransitionOnTriggerUp[1] = "Idle"; + +isLarge = false; +maxDepSlope = 360; +deploySound = ItemPickupSound; + +minDeployDis = 0; +maxDeployDis = 50.0; +}; + +datablock ItemData(DoorDeployable) { +className = Pack; +catagory = "Deployables"; +shapeFile = "stackable1s.dts"; +mass = 1; +elasticity = 0.2; +friction = 0.6; +pickupRadius = 1; +rotate = true; +image = "DoorDeployableImage"; +pickUpName = "a door pack made by Linker"; +heatSignature = 0; +emap = true; +}; + +function DoorDeployableImage::testObjectTooClose(%item) { +return ""; +} + +function DoorDeployableImage::testNoTerrainFound(%item) { +// don't check this for non-Landspike turret deployables +} + +function DoorDeployable::onPickup(%this, %obj, %shape, %amount) { +// created to prevent console errors +} + +function DoorDeployableImage::onDeploy(%item, %plyr, %slot) { + %className = "StaticShape"; + %grounded = 0; + if (%item.surface.getClassName() $= TerrainBlock) + %grounded = 1; + + %playerVector = vectorNormalize(-1 * getWord(%plyr.getEyeVector(),1) SPC getWord(%plyr.getEyeVector(),0) SPC "0"); + + if (%item.surfaceinher == 0) { + if (vAbs(floorVec(%item.surfaceNrm,100)) $= "0 0 1"){ + %item.surfaceNrm2 = %playerVector; + } + else{ + %item.surfaceNrm2 = vectorNormalize(vectorCross(%item.surfaceNrm,"0 0 1")); + } + } + + %rot1 = fullRot(%item.surfaceNrm,%item.surfaceNrm2); + + %scale1 = "0.5 6 160"; + %scale2 = "0.5 8 160"; + %dataBlock = %item.deployed; + + %space = rayDist(%item.surfacePt SPC %item.surfaceNrm,%scale1,$AllObjMask); + if (%space != getWord(%scale1,1)) + %type = true; + %scale1 = getWord(%scale1,0) SPC getWord(%scale1,0) SPC %space; + + + %mCenter = "0 0 -0.5"; + %pad = pad(%item.surfacePt SPC %item.surfaceNrm SPC %item.surfaceNrm2,%scale2,%mCenter); + %scale2 = getWords(%pad,0,2); + %item.surfacePt2 = getWords(%pad,3,5); + + //%vec1 = realVec(getWord(%item.surface,0),%item.surfaceNrm); + //%vec1 = realVec(%pad,%item.surfaceNrm); + %vec1 =validateVal(MatrixMulVector("0 0 0",%item.surfaceNrm)); + + if (!%scaleIsSet){ + %scale1 = vectorMultiply(%scale1,1/4 SPC 1/3 SPC 2); + %scale2 = vectorMultiply(%scale2,1/4 SPC 1/3 SPC 2); + %x = (getWord(%scale2,1)/0.166666)*0.125; + %scale3 = %x SPC 0.166666 SPC getWord(%scale1,2); + } + + + + %dir1 = VectorNormalize(vectorSub(%item.surfacePt,%item.surfacePt2)); + %adjust1 = vectorNormalize(vectorProject(%dir1,vectorCross(%item.surfaceNrm,%item.surfaceNrm2))); + %offset1 = -0.5; + %adjust1 = vectorScale(%adjust1,-0.5 * %offset1); + + %deplObj = new (%className)() { + dataBlock = %dataBlock; + scale = %scale3; + }; + %deplObj.closedscale = %scale3; + %deplObj.openedscale = getwords(%scale3,0,1) SPC 0.1; +//////////////////////////Apply settings////////////////////////////// + + // exact: + //%deplObj.setTransform(%item.surfacePt SPC %rot1); + %deplObj.setTransform(vectorAdd(VectorAdd(%item.surfacePt2, VectorScale(%vec1,getword(%scale3,2)/-4)),%adjust1) SPC %rot1); + + // misc info + addDSurface(%item.surface,%deplObj); + // [[Settings]]: + + %deplObj.grounded = %grounded; + %deplObj.needsFit = 1; + %deplObj.isdoor = 1; + // [[Normal Stuff]]: + + // set team, owner, and handle + %deplObj.team = %plyr.client.team; + %deplObj.setOwner(%plyr); + + // set power frequency + %deplObj.powerFreq = %plyr.powerFreq; + + // set the sensor group if it needs one + if (%deplObj.getTarget() != -1) + setTargetSensorGroup(%deplObj.getTarget(), %plyr.client.team); + + // place the deployable in the MissionCleanup/Deployables group (AI reasons) + addToDeployGroup(%deplObj); + + //let the AI know as well... + AIDeployObject(%plyr.client, %deplObj); + + // play the deploy sound + serverPlay3D(%item.deploySound, %deplObj.getTransform()); + + // increment the team count for this deployed object + $TeamDeployedCount[%plyr.team, %item.item]++; + + %deplObj.deploy(); + +// Power object +checkPowerObject(%deplObj); +%deplobj.slidevec=%deplobj.dsurface.getedge("0 0 0"); + +%deplobj.timeout=getWord($expertSetting["Door",%plyr.expertSet],0); +%deplobj.initialtransform=%deplobj.gettransform(); +%deplobj.hasslided=0; + +if (%plyr.packset==1) +%deplobj.toggletype=1; + +if (%plyr.packset==2) { +%deplobj.toggletype=0; +%deplobj.powercontrol=1; +} + +if (%plyr.packset==3) { +%deplobj.toggletype=1; +%deplobj.powercontrol=1; +} + +if (%plyr.packset==0) +%deplobj.toggletype=0; + +if (%pad) +deployEffect(%deplObj,%item.surfacePt,%item.surfaceNrm,"pad"); +return %deplObj; +} + +function deployeddoor::onDestroyed(%this, %obj, %prevState) { +if (%obj.isRemoved) +return; +%obj.isRemoved = true; +Parent::onDestroyed(%this, %obj, %prevState); +$TeamDeployedCount[%obj.team, DoorDeployable]--; +remDSurface(%obj); +%obj.schedule(500, "delete"); +cascade(%obj); +fireBallExplode(%obj,1); +} + +function DoorDeployableImage::onMount(%data, %obj, %node) { +%obj.hasDoor = true; // set for blastcheck +%obj.packSet = 0; +%obj.expertSet = 3; +displayPowerFreq(%obj); +} + +function DoorDeployableImage::onUnmount(%data, %obj, %node) { +%obj.hasDoor = ""; +%obj.packSet = 0; +%obj.expertSet = 0; +} + + + +function open(%obj){ +if (!isObject(%obj)) + return; +if (%obj.issliding !=1 && %obj.canmove == true){ + %obj.issliding = 1; + %obj.moving = "open"; + %obj.dist = getWord(%obj.scale,2); + %amount1 = %obj.dist*100; + %amount2 = mfloor(%amount1); + %obj.amount = %amount2/5; + %obj.oldscale = %obj.scale; + %obj.prevscale=%obj.scale; +%obj.canmove = false; +} + +if (getWord(%obj.scale,2)<0.4){ + %obj.issliding = 0; + %obj.scale = getWord(%obj.scale,0) SPC getWord(%obj.scale,1) SPC 0.1; + %obj.settransform(%obj.gettransform()); + %obj.state = "opened"; + %obj.openedscale = %obj.scale; + if (%obj.toggletype ==0) + schedule(%obj.timeout*1000,0,"close",%obj,1); + else + %obj.canmove = true; + return; + } +%obj.scale = getWord(%obj.scale,0) SPC getWord(%obj.scale,1) SPC getWord(%obj.prevscale,2)-0.4; +%obj.settransform(%obj.gettransform()); +%obj.prevscale=%obj.scale; +schedule(40,0,"open",%obj); +} +///////////////////// +///////////////////// +function close(%obj,%timeout){ +if (!isObject(%obj)) + return; +if (%obj.issliding !=1){ + %obj.issliding = 1; + %obj.moving = "close"; + %obj.dist = getWord(%obj.oldscale,2); + %amount1 = %obj.dist*100; + %amount2 = mfloor(%amount1); + %obj.amount = %amount2/10; + %obj.prevscale=%obj.scale; +%obj.canmove = false; +} + +if (getWord(%obj.scale,2)>getWord(%obj.closedscale,2)-0.2){ + %obj.issliding = 0; + %obj.scale =getWord(%obj.scale,0) SPC getWord(%obj.scale,1) SPC getWord(%obj.closedscale,2); + %obj.settransform(%obj.gettransform()); + %obj.state = "closed"; + %obj.closedscale = %obj.scale; + %obj.canmove = true; + return; + } +%obj.scale = getWord(%obj.scale,0) SPC getWord(%obj.scale,1) SPC getWord(%obj.prevscale,2)+0.4; +%obj.settransform(%obj.gettransform()); +%obj.prevscale=%obj.scale; +schedule(40,0,"close",%obj); +} + + diff --git a/scripts/packs/energizer.cs b/scripts/packs/energizer.cs new file mode 100644 index 0000000..47d61d6 --- /dev/null +++ b/scripts/packs/energizer.cs @@ -0,0 +1,385 @@ +//-------------------------------------------------------------------------- +// Deployable Energizer +//-------------------------------------- + +datablock StaticShapeData(DeployedEnergizer) : StaticShapeDamageProfile { + className = "energizer"; + shapeFile = "deploy_sensor_motion.dts"; + + maxDamage = 0.5; + destroyedLevel = 0.5; + disabledLevel = 0.3; + + isShielded = true; + energyPerDamagePoint = 30; + maxEnergy = 50; + rechargeRate = 0.05; + + explosion = SatchelMainExplosion; + underwaterExplosion = UnderwaterSatchelMainExplosion; + + expDmgRadius = 20.0; + expDamage = 1.25; + expImpulse = 1500.0; + + dynamicType = $TypeMasks::StationObjectType; + renderWhenDestroyed = false; + + hasLight = true; + lightType = "PulsingLight"; + lightColor = "0.1 0.1 0.8 1.0"; + lightTime = "100"; + lightRadius = "3"; + + humSound = GeneratorHumSound; + + EnergizeOthers = true; + EnergizeRadius = 35; + + dynamicType = $TypeMasks::StaticShapeObjectType; + deployedObject = true; + cmdCategory = "DSupport"; + cmdIcon = CMDSwitchIcon; + cmdMiniIconName = "commander/MiniIcons/com_switch_grey"; + targetNameTag = 'Deployed'; + targetTypeTag = 'Energizer'; + deployAmbientThread = true; + debrisShapeName = "debris_generic_small.dts"; + debris = DeployableDebris; + heatSignature = 0; +}; + +datablock ItemData(EnergizerLight) : StaticShapeDamageProfile { + className = "energizerlight"; + shapeFile = "beacon.dts"; + + maxDamage = 2.0; + destroyedLevel = 2.0; + disabledLevel = 2.0; + + mass = 1; + elasticity = 0.1; + friction = 0.9; + + collideable = 1; + pickupRadius = 1; + sticky = false; + + explosion = HandGrenadeExplosion; + expDmgRadius = 1.0; + expDamage = 0.1; + expImpulse = 200.0; + + dynamicType = $TypeMasks::StaticShapeObjectType; + deployedObject = true; + + hasLight = true; + lightType = "PulsingLight"; + lightColor = "0.8 0.1 0.1 1.0"; + lightTime = "100"; + lightRadius = "1"; + + deployAmbientThread = true; + debrisShapeName = "debris_generic_small.dts"; + debris = DeployableDebris; + heatSignature = 0; +}; + +datablock ShapeBaseImageData(EnergizerDeployableImage) { + mass = 1; + shapeFile = "deploy_sensor_motion.dts"; + scale = 2.5 / 3.85 @ " " @ 2.5 / 3.1 @ " " @ 5 / 3.1; + item = EnergizerDeployable; + mountPoint = 1; + offset = "0 0 0"; + deployed = EnergizerDeployed; + stateName[0] = "Idle"; + stateTransitionOnTriggerDown[0] = "Activate"; + + hasLight = true; + lightType = "PulsingLight"; + lightColor = "0.1 0.1 0.8 1.0"; + lightTime = "100"; + lightRadius = "3"; + + stateName[1] = "Activate"; + stateScript[1] = "onActivate"; + stateTransitionOnTriggerUp[1] = "Idle"; + + isLarge = true; + emap = true; + maxDepSlope = 360; + deploySound = TurretDeploySound; + minDeployDis = 0.5; + maxDeployDis = 5.0; +}; + +datablock ItemData(EnergizerDeployable) { + className = Pack; + catagory = "Deployables"; + shapeFile = "deploy_sensor_motion.dts"; + scale = 2.5 / 3.85 @ " " @ 2.5 / 3.1 @ " " @ 5 / 3.1; + mass = 1; + + hasLight = true; + lightType = "PulsingLight"; + lightColor = "0.1 0.1 0.8 1.0"; + lightTime = "500"; + lightRadius = "3"; + + elasticity = 0.2; + friction = 0.6; + pickupRadius = 1; + rotate = false; + image = "EnergizerDeployableImage"; + pickUpName = "an energizer pack"; + emap = true; +}; + +//-------------------------------------------------------------------------- +// Functions +//-------------------------------------- + +function EnergizerDeployableImage::testObjectTooClose(%item,%surfacePt,%plyr) { + %mask = ($TypeMasks::VehicleObjectType | $TypeMasks::MoveableObjectType | + $TypeMasks::StaticShapeObjectType | + $TypeMasks::ForceFieldObjectType | $TypeMasks::ItemObjectType | + $TypeMasks::PlayerObjectType | $TypeMasks::TurretObjectType); + + InitContainerRadiusSearch(%item.surfacePt,30,%mask); + + while ((%test = containerSearchNext()) != 0) { + if (%test.team !$= "" && %test.team != %plyr.team) + return %test; + } + Parent::testObjectTooClose(%item,%surfacePt,%plyr); +} + +function DeployedEnergizer::disassemble(%data,%plyr,%hTgt) { + %hTgt.l1.schedule(500, "delete"); + %hTgt.l2.schedule(500, "delete"); + %hTgt.l3.schedule(500, "delete"); + %hTgt.l4.schedule(500, "delete"); + disassemble(%data,%plyr,%hTgt); +} + +function DeployedEnergizer::onDestroyed(%this, %obj, %prevState) { + if (%obj.isRemoved) + return; + %obj.isRemoved = true; + Parent::onDestroyed(%this, %obj, %prevState); + $TeamDeployedCount[%obj.team, EnergizerDeployable]--; + remDSurface(%obj); + %obj.schedule(500, "delete"); + %obj.l1.schedule(500, "delete"); + %obj.l2.schedule(500, "delete"); + %obj.l3.schedule(500, "delete"); + %obj.l4.schedule(500, "delete"); + + RadiusExplosion(%obj, %obj.getWorldBoxCenter(), %obj.expDmgRadius, %obj.expDamage, %obj.expImpulse, %obj, $DamageType::Explosion); + fireBallExplode(%obj,10); +} + +function EnergizerDeployableImage::onDeploy(%item, %plyr, %slot) { + //Object + %className = "StaticShape"; + + %playerVector = vectorNormalize(-1 * getWord(%plyr.getEyeVector(),1) SPC getWord(%plyr.getEyeVector(),0) SPC "0"); + + if (%item.surfaceinher == 0) { + if (vAbs(floorVec(%item.surfaceNrm,100)) $= "0 0 1") + %item.surfaceNrm2 = %playerVector; + else + %item.surfaceNrm2 = vectorNormalize(vectorCross(%item.surfaceNrm,"0 0 1")); + } + + %rot = fullRot(%item.surfaceNrm,%item.surfaceNrm2); + %scale = "5 5 5"; + + %deplObj = new (%className)() { + dataBlock = "DeployedEnergizer"; + scale = %scale; + }; + + // set orientation + %deplObj.setTransform(%item.surfacePt SPC %rot); + + //Object + %className = "Item"; + %deplObj.l1 = new (%className)() { + dataBlock = "EnergizerLight"; + position = vectorAdd(%item.surfacePt, "2 0 1"); + rotation = %rot; + scale = "1 1 1"; + }; + + %deplObj.l2 = new (%className)() { + dataBlock = "EnergizerLight"; + position = vectorAdd(%item.surfacePt, "0 2 1"); + rotation = %rot; + scale = "1 1 1"; + }; + + %deplObj.l3 = new (%className)() { + dataBlock = "EnergizerLight"; + position = vectorAdd(%item.surfacePt, "-2 0 1"); + rotation = %rot; + scale = "1 1 1"; + }; + + %deplObj.l4 = new (%className)() { + dataBlock = "EnergizerLight"; + position = vectorAdd(%item.surfacePt, "0 -2 1"); + rotation = %rot; + scale = "1 1 1"; + }; + + %deplObj.team = %plyr.client.team; + %deplObj.setOwner(%plyr); + %deplObj.l1.team = %plyr.client.team; + %deplObj.l1.setOwner(%plyr); + %deplObj.l2.team = %plyr.client.team; + %deplObj.l2.setOwner(%plyr); + %deplObj.l3.team = %plyr.client.team; + %deplObj.l3.setOwner(%plyr); + %deplObj.l4.team = %plyr.client.team; + %deplObj.l4.setOwner(%plyr); + addDSurface(%item.surface,%deplObj); + + if (%deplObj.getTarget() != -1) + setTargetSensorGroup(%deplObj.getTarget(), %plyr.client.team); + if (%deplObj.l1.getTarget() != -1) + setTargetSensorGroup(%deplObj.l1.getTarget(), %plyr.client.team); + if (%deplObj.l2.getTarget() != -1) + setTargetSensorGroup(%deplObj.l1.getTarget(), %plyr.client.team); + if (%deplObj.l3.getTarget() != -1) + setTargetSensorGroup(%deplObj.l1.getTarget(), %plyr.client.team); + if (%deplObj.l4.getTarget() != -1) + setTargetSensorGroup(%deplObj.l1.getTarget(), %plyr.client.team); + + addToDeployGroup(%deplObj); + addToDeployGroup(%deplObj.l1); + addToDeployGroup(%deplObj.l2); + addToDeployGroup(%deplObj.l3); + addToDeployGroup(%deplObj.l4); + + AIDeployObject(%plyr.client, %deplObj); + AIDeployObject(%plyr.client, %deplObj.l1); + AIDeployObject(%plyr.client, %deplObj.l2); + AIDeployObject(%plyr.client, %deplObj.l3); + AIDeployObject(%plyr.client, %deplObj.l4); + + serverPlay3D(%item.deploySound, %deplObj.getTransform()); + $TeamDeployedCount[%plyr.team, %item.item]++; + %deplObj.deploy(); + + %deplObj.playThread($AmbientThread, "ambient"); + + %plyr.unmountImage(%slot); + %plyr.decInventory(%item.item, 1); + + return %deplObj; +} + +function EnergizerDeployable::onPickup(%this, %obj, %shape, %amount) { + // created to prevent console errors +} + +function EnergizeLoop() { + if (!isObject(MissionCleanup)) { + schedule(10000, 0, "StartEnergizeLoop"); + return; + } + + %dep = nameToID("MissionCleanup/Deployables"); + %clCount = ClientGroup.getCount(); + %depCount = %dep.getCount(); + for (%i=0;%i<%clCount;%i++) { + ClientGroup.getObject(%i).shouldEnergize = 0; + } + for (%i=0;%i<%depCount;%i++) { + %obj = %dep.getObject(%i); + if (isObject(%obj)) { + %data = %obj.getDataBlock(); + if (%data) { + if (%data.energizeOthers && %obj.isEnabled()) { + %pos = posFromTransform(%obj.getTransform()); + for(%i2=0;%i2<%clCount;%i2++) { + %obj2 = ClientGroup.getObject(%i2).player; + if ((%obj2) && (%obj2 != %obj) && (%obj2.team == %obj.team)) { + %pos2 = %obj2.getPosition(); + if (vectorDist(%pos, %pos2) < %data.EnergizeRadius && %obj2.getArmorSize() $= "Heavy") + %obj2.client.shouldEnergize = 1; + } + } + } + } + } + } + for (%i=0;%i<%clCount;%i++) { + %client = ClientGroup.getObject(%i); + %obj = %client.player; + if (isObject(%obj)) { + if ((%client.shouldEnergize) && (!%obj.energized)) { + %obj.energized = 1; + if (!%obj.hasEnergizer) + %obj.setRechargeRate(%obj.getRechargeRate() + 0.5); + messageClient(%obj.client, 'msgClient', '\c2Entering energizer coverage.'); + } + else if (!%client.shouldEnergize && %obj.energized) { + %obj.energized = ""; + if (%obj.hasEnergizer) + messageClient(%obj.client, 'msgClient', '\c2Leaving energizer coverage, switching to energizer pack.'); + else { + %obj.setRechargeRate(%obj.getRechargeRate() - 0.5); + messageClient(%obj.client, 'msgClient', '\c2Leaving energizer coverage, switching to armor power.'); + } + } + } + } + for (%i=0;%i<%depCount;%i++) { + %obj = %dep.getObject(%i); + if (isObject(%obj)) { + %data = %obj.getDataBlock(); + if (%data.energizeOthers) { + if (%obj.energized) + %obj.energized = ""; + } + else if ((%obj.shouldEnergize) && (!%obj.energized)) { + %obj.energized = 1; + %obj.setRechargeRate(%obj.getRechargeRate() + 0.5); + } + else if ((!%obj.shouldEnergize) && (%obj.energized)) { + %obj.energized = ""; + %obj.setRechargeRate(%obj.getRechargeRate() - 0.5); + } + } + } + schedule(1000, 0, "EnergizeLoop"); +} + +function StartEnergizeLoop() { + $EnergizeLoop = 1; + if (!isObject(MissionCleanup)) { + schedule(10000, 0, "StartEnergizeLoop"); + return; + } + %depGroup = nameToID("MissionCleanup/Deployables"); + if (%depGroup <= 0) { + %depGroup = new SimGroup("Deployables"); + MissionCleanup.add(%depGroup); + } + EnergizeLoop(); +} + +function EnergizerDeployableImage::onMount(%data, %obj, %node) { + %obj.hasEnergizer = true; + if (!%obj.energized) + %obj.setRechargeRate(%obj.getRechargeRate() + 0.5); +} + +function EnergizerDeployableImage::onUnmount(%data, %obj, %node) { + %obj.hasEnergizer = ""; + if (!%obj.energized) + %obj.setRechargeRate(%obj.getRechargeRate() - 0.5); +} diff --git a/scripts/packs/escapepodpack.cs b/scripts/packs/escapepodpack.cs new file mode 100644 index 0000000..d362882 --- /dev/null +++ b/scripts/packs/escapepodpack.cs @@ -0,0 +1,393 @@ +// Escape Pod Pack + +datablock AudioProfile(EscapePodChargeSound) { + filename = "fx/misc/cannonstart.wav"; + description = AudioDefault3d; + preload = true; +}; + +datablock AudioProfile(EscapePodBeepSound) { + filename = "fx/misc/warning_beep.wav"; + description = AudioClosest3d; + preload = true; +}; + +datablock AudioProfile(EscapePodLaunchSound) { + filename = "fx/Bonuses/high-level4-blazing.wav"; + description = AudioBIGExplosion3d; + preload = true; +}; + +datablock AudioProfile(EscapePodLaunchSound2) { + filename = "fx/Bonuses/down_passback3_rocket.wav"; + description = AudioBIGExplosion3d; + preload = true; +}; + +datablock AudioProfile(EscapePodReloadSound) { + filename = "fx/powered/turret_heavy_reload.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(EscapePodFadeSound) { + filename = "fx/Bonuses/upward_perppass2_quark.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock StaticShapeData(DeployedEscapePod) : StaticShapeDamageProfile { + className = "escapepod"; + shapeFile = "TR2weapon_mortar.dts"; + + maxDamage = 1; + destroyedLevel = 1; + disabledLevel = 1; + + isShielded = true; + energyPerDamagePoint = 75; + maxEnergy = 50; + rechargeRate = 0.35; + + explosion = ShapeExplosion; + expDmgRadius = 8.0; + expDamage = 0.4; + expImpulse = 1500; + + dynamicType = $TypeMasks::StaticShapeObjectType; + deployedObject = true; + cmdCategory = "DSupport"; + cmdIcon = CMDSensorIcon; + cmdMiniIconName = "commander/MiniIcons/com_deploymotionsensor"; + targetNameTag = 'Deployed'; + targetTypeTag = 'Escape Pod'; + deployAmbientThread = false; + debrisShapeName = "debris_generic.dts"; + debris = DeployableDebris; + heatSignature = 1; + emap = true; +}; + +datablock ShapeBaseImageData(EscapePodDeployableImage) { + mass = 1; + emap = true; + shapeFile = "stackable1s.dts"; + item = EscapePodDeployable; + mountPoint = 1; + offset = "0 0 0"; + deployed = DeployedEscapePod; + heatSignature = 0; + + stateName[0] = "Idle"; + stateTransitionOnTriggerDown[0] = "Activate"; + + stateName[1] = "Activate"; + stateScript[1] = "onActivate"; + stateTransitionOnTriggerUp[1] = "Idle"; + + isLarge = true; + maxDepSlope = 360; + deploySound = ItemPickupSound; + + minDeployDis = 0.25; + maxDeployDis = 5; +}; + +datablock ItemData(EscapePodDeployable) { + className = Pack; + catagory = "Deployables"; + shapeFile = "stackable1s.dts"; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 3; + rotate = true; + image = "EscapePodDeployableImage"; + pickUpName = "an escape pod pack"; + heatSignature = 0; + emap = true; +}; + +function EscapePodDeployableImage::testNoTerrainFound(%item) { + // don't check this for non-Landspike turret deployables +} + +function EscapePodDeployable::onPickup(%this, %obj, %shape, %amount) { + // created to prevent console errors +} + +function EscapePodDeployableImage::onDeploy(%item, %plyr, %slot) { + %className = "StaticShape"; + + %playerVector = vectorNormalize(-1 * getWord(%plyr.getEyeVector(),1) SPC getWord(%plyr.getEyeVector(),0) SPC "0"); + + if (vAbs(floorVec(%item.surfaceNrm,100)) $= "0 0 1") + %item.surfaceNrm2 = %playerVector; + else + %item.surfaceNrm2 = vectorNormalize(vectorCross(%item.surfaceNrm,"0 0 1")); + + %rot = fullRot(%item.surfaceNrm,%item.surfaceNrm2); + + %deplObj = new (%className)() { + dataBlock = DeployedEscapePod; + scale = "4 2 4"; + impulse = $packSetting["escapepod",%plyr.packSet]; + }; + + %deplObj.lTarget = new StaticShape () { + datablock = DeployedLTarget; + scale = vectorMultiply("1 3 0.25",1/4 SPC 1/3 SPC 2); + }; + + %deplObj.lTarget.lMain = %deplObj; + + // set orientation + %deplObj.lTarget.setTransform(%item.surfacePt SPC %rot); + adjustEscapePod(%deplObj); + escapePodLoop(%deplObj); + + // set the recharge rate right away + if (%deplObj.getDatablock().rechargeRate) + %deplObj.setRechargeRate(%deplObj.getDatablock().rechargeRate); + + // set team, owner, and handle + %deplObj.team = %plyr.client.Team; + %deplObj.setOwner(%plyr); + if (%deplObj.lTarget) { + %deplObj.lTarget.team = %plyr.client.Team; + %deplObj.lTarget.setOwner(%plyr); + } + + // set the sensor group if it needs one + if (%deplObj.getTarget() != -1) + setTargetSensorGroup(%deplObj.getTarget(), %plyr.client.team); + + // place the deployable in the MissionCleanup/Deployables group (AI reasons) + addToDeployGroup(%deplObj); + if (%deplObj.lTarget) + addToDeployGroup(%deplObj.lTarget); + + //let the AI know as well... + AIDeployObject(%plyr.client, %deplObj); + if (%deplObj.lTarget) + AIDeployObject(%plyr.client,%deplObj.lTarget); + + // play the deploy sound + serverplay3D(%item.deploySound, %deplObj.getTransform()); + + // increment the team count for this deployed object + $TeamDeployedCount[%plyr.team, %item.item]++; + + %deplObj.deploy(); + + addDSurface(%item.surface,%deplObj); + if (%deplObj.lTarget) + addDSurface(%deplObj,%deplObj.lTarget); + + // take the deployable off the player's back and out of inventory + %plyr.unmountImage(%slot); + %plyr.decInventory(%item.item, 1); + + return %deplObj; +} + +function DeployedEscapePod::onDestroyed(%this,%obj,%prevState) { + if (%obj.isRemoved) + return; + %obj.isRemoved = true; + Parent::onDestroyed(%this,%obj,%prevState); + $TeamDeployedCount[%obj.team, EscapePodDeployable]--; + remDSurface(%obj); + %obj.schedule(500, "delete"); + if (isObject(%obj.lTarget)) + %obj.lTarget.schedule(500, "delete"); + if (isObject(%obj.podVehicle)) + %obj.podVehicle.schedule(500,setDamageState,Destroyed); +} + +function DeployedEscapePod::disassemble(%data,%plyr,%obj) { + if (isObject(%obj.podVehicle)) + %obj.podVehicle.startFade(500,0,1); + %obj.podVehicle.schedule(500,delete); + disassemble(%data,%plyr,%obj); +} + +function adjustEscapePod(%obj) { + if (!isObject(%obj)) + return; + %lTarget = %obj.lTarget; + %pos = %lTarget.getPosition(); + %rot = %lTarget.getRotation(); + %nrm = realVec(%lTarget,"0 0 1"); + %obj.setTransform(vectorAdd(%pos,vectorScale(%nrm,1.25)) SPC %rot); +} + +function escapePodLoop(%obj) { + if (!isObject(%obj)) + return; + if (%obj.getDamageState() !$= "Enabled") + return; + cancel(%obj.escapePodLoop); + %lTarget = %obj.lTarget; + %pos = %lTarget.getPosition(); + %nrm = realVec(%lTarget,"0 0 1"); + %nrm2 = realVec(%lTarget,"1 0 0"); + %epod = %obj.podVehicle; + if (isObject(%epod)) { + if (%epod.player) { + %player = %epod.getMountedObject(0); + if (isObject(%player)) { + if (%player.getState() $= "Dead") { + %remove = true; + if (!%player.podFaded) { + %player.startFade(2000,0,1); + %player.podFaded = true; + } + } + } + else + %remove = true; + } + else { + // Remove when launched manually (no player) + if (%epod.launched) + %remove = true; + } + if (%remove == true) + %epod.getDataBlock().fadeOutVehicle(%epod); + } + else { + %epod = new HoverVehicle() { + dataBlock = "EscapePodVehicle"; + scale = "1 1 1"; + team = %obj.team; + mountable = "1"; + selfpower = "1"; + }; + %obj.podVehicle = %epod; + setTargetSensorGroup(%epod.getTarget(),%epod.team); + %epod.launcher = %obj; + %epod.setFrozenState(true); + %epod.setTransform(vectorAdd(%pos,vectorScale(%nrm,1)) SPC fullRot(%nrm,vectorScale(%nrm2,-1))); + %obj.play3D(EscapePodReloadSound); + %obj.stopThread($AmbientThread); + %obj.setThreadDir($AmbientThread,0); + %obj.playThread($AmbientThread,"recoil"); + %obj.schedule(1000,stopThread,$AmbientThread); + } + %obj.escapePodLoop = schedule(1000,0,escapePodLoop,%obj); +} + +function EscapePodDeployableImage::onMount(%data, %obj, %node) { + %obj.hasEscapePod = true; // set for podcheck + %obj.packSet = 7; + %obj.expertSet = 0; +} + +function EscapePodDeployableImage::onUnmount(%data, %obj, %node) { + %obj.packSet = 0; + %obj.expertSet = 0; + %obj.hasEscapePod = ""; +} + +function EscapePodVehicle::isBlocked(%data,%obj,%player) { + %pos = %obj.getPosition(); + %startPos = vectorAdd(%pos,vectorScale(realVec(%obj,"0 -1 0"),2)); + %endPos = vectorAdd(%pos,vectorScale(realVec(%obj,"0 1 0"),2)); + %mask = $TypeMasks::VehicleObjectType | $TypeMasks::StationObjectType | $TypeMasks::GeneratorObjectType | $TypeMasks::SensorObjectType | $TypeMasks::TurretObjectType | $TypeMasks::TerrainObjectType | $TypeMasks::InteriorObjectType | $TypeMasks::ForceFieldObjectType | $TypeMasks::StaticObjectType | $TypeMasks::MoveableObjectType | $TypeMasks::DamagableItemObjectType; + %res = containerRayCast(%startPos,%endPos,%mask,%obj); + if (%res) + return 1; + return 0; +} + +function EscapePodVehicle::playerMounted(%data, %obj, %player, %node) { + if (%obj.player) + return; + %obj.player = %player; + %obj.playerMountedTime = getSimTime(); +// commandToClient(%player.client, 'setHudMode', 'Pilot', "Hoverbike", %node); + + // update observers who are following this guy... + if ( %player.client.observeCount > 0 ) + resetObserveFollow( %player.client, false ); + + %obj.play3D(EscapePodBeepSound); + %data.schedule(1000,actionThreadPlayer,%player,"scoutRoot"); + %obj.schedule(1500,play3D,EscapePodChargeSound); + %data.schedule(3000,launchPod,%obj,%player,%node); +} + +function EscapePodVehicle::actionThreadPlayer(%data,%player,%thread) { + if (!isObject(%player)) + return; + if (%player.getState() $= "Dead") { + %player.startFade(2000,0,1); + %player.podFaded = true; + } + else + %player.setActionThread(%thread,true); +} + +function EscapePodVehicle::launchPod(%data,%obj,%player,%node) { + if (!isObject(%obj)) + return; + %obj.launched = true; + %obj.play3D(EscapePodLaunchSound); + %obj.play3D(EscapePodLaunchSound2); + %launcher = %obj.launcher; + if (isObject(%launcher)) { + %launcher.stopThread($AmbientThread); + %launcher.setThreadDir($AmbientThread,1); + %launcher.playThread($AmbientThread,"recoil"); + %launcher.schedule(1000,stopThread,$AmbientThread); + } + %obj.setFrozenState(false); + %obj.applyImpulse(%obj.getPosition(),vectorScale(realVec(%obj,"0 1 0"),%launcher.impulse)); + for(%i = 0; %i < 10; %i++) + %data.schedule((%i * %i) * 10,emitLaunchPuff,%obj); +} + +function EscapePodVehicle::emitLaunchPuff(%data,%obj) { + if (!isObject(%obj)) + return; + %em = new ParticleEmissionDummy() { + dataBlock = "defaultEmissionDummy"; + emitter = "VehicleLGESmokeEMitter"; + position = %obj.getPosition(); + scale = "1 1 1"; + velocity = "1"; + }; + MissionCleanup.add(%em); + %em.schedule(1000,"delete"); +} + +//function EscapePodVehicle::onDestroyed(%data, %obj, %prevState) { +// Parent::onDestroyed(%data, %obj, %prevState); +//} + + +//function EscapePodVehicle::playerDismounted(%data, %obj, %player) { +// Parent::playerDismounted(%data, %obj, %player); +//} + +function EscapePodVehicle::fadeOutVehicle(%data,%obj) { + if (%obj.faded) + return; + %obj.faded = true; + %obj.startFade(1000,4000,1); + %obj.schedule(5000,delete); + %obj.schedule(4000,play3D,EscapePodFadeSound); +} + +function EscapePodVehicle::onAdd(%this, %obj) { + Parent::onAdd(%this, %obj); + setTargetSensorGroup(%obj.getTarget(),%obj.team); +} + +function displayEscapePodBoostPower(%plyr) { + %line = $packSetting["escapepod",%plyr.packSet]; + %max = $packSetting["escapepod",$packSettings["escapepod"]]; + %power = mAbs(mFloatLength(100 / %max * %line,1)); + bottomPrint(%plyr.client,"Escape Pod booster set to " @ %power @ "% power" ,2,1); +} diff --git a/scripts/packs/forcefieldpack.cs b/scripts/packs/forcefieldpack.cs new file mode 100644 index 0000000..e58d966 --- /dev/null +++ b/scripts/packs/forcefieldpack.cs @@ -0,0 +1,518 @@ +//--------------------------------------------------------- +// Deployable Force Field +//--------------------------------------------------------- + +// Translucencies +%noPassTrans = 1.0; +%teamPassTrans = 0.6; +%allPassTrans = 0.2; + +%dimDiv = 4; + +// RGB +%colourOn = 0.3; +%colourOff = 0.0; + +datablock ForceFieldBareData(DeployedForceField) { + className = "forcefield"; + fadeMS = 1000; + baseTranslucency = %allPassTrans; + powerOffTranslucency = %allPassTrans / %dimDiv; + teamPermiable = false; + otherPermiable = false; + color = "1.0 1.0 1.0"; + powerOffColor = "0.0 0.0 0.0"; + targetNameTag = 'Force Field'; + targetTypeTag = 'ForceField'; + texture[0] = "skins/forcef1"; + texture[1] = "skins/forcef2"; + texture[2] = "skins/forcef3"; + texture[3] = "skins/forcef4"; + texture[4] = "skins/forcef5"; + framesPerSec = 1; // 10 + numFrames = 5; + scrollSpeed = 15; + umapping = 0.01; // 1.0 + vmapping = 0.01; // 0.15 + deployedFrom = ForceFieldDeployable; + needsPower = true; +}; + +// No pass +datablock ForceFieldBareData(DeployedForceField0) : DeployedForceField { + baseTranslucency = %noPassTrans; + powerOffTranslucency = %noPassTrans / %dimDiv; + teamPermiable = false; + otherPermiable = false; + color = %colourOn SPC %colourOn SPC %colourOn; + powerOffColor = "0.0 0.0 0.0"; +}; + +datablock ForceFieldBareData(DeployedForceField1) : DeployedForceField { + baseTranslucency = %noPassTrans; + powerOffTranslucency = %noPassTrans / %dimDiv; + teamPermiable = false; + otherPermiable = false; + color = %colourOn SPC %colourOff SPC %colourOff; + powerOffColor = "0.0 0.0 0.0"; +}; + +datablock ForceFieldBareData(DeployedForceField2) : DeployedForceField { + baseTranslucency = %noPassTrans; + powerOffTranslucency = %noPassTrans / %dimDiv; + teamPermiable = false; + otherPermiable = false; + color = %colourOff SPC %colourOn SPC %colourOff; + powerOffColor = "0.0 0.0 0.0"; +}; + +datablock ForceFieldBareData(DeployedForceField3) : DeployedForceField { + baseTranslucency = %noPassTrans; + powerOffTranslucency = %noPassTrans / %dimDiv; + teamPermiable = false; + otherPermiable = false; + color = %colourOff SPC %colourOff SPC %colourOn; + powerOffColor = "0.0 0.0 0.0"; +}; + +datablock ForceFieldBareData(DeployedForceField4) : DeployedForceField { + baseTranslucency = %noPassTrans; + powerOffTranslucency = %noPassTrans / %dimDiv; + teamPermiable = false; + otherPermiable = false; + color = %colourOff SPC %colourOn SPC %colourOn; + powerOffColor = "0.0 0.0 0.0"; +}; + +datablock ForceFieldBareData(DeployedForceField5) : DeployedForceField { + baseTranslucency = %noPassTrans; + powerOffTranslucency = %noPassTrans / %dimDiv; + teamPermiable = false; + otherPermiable = false; + color = %colourOn SPC %colourOff SPC %colourOn; + powerOffColor = "0.0 0.0 0.0"; +}; + +datablock ForceFieldBareData(DeployedForceField6) : DeployedForceField { + baseTranslucency = %noPassTrans; + powerOffTranslucency = %noPassTrans / %dimDiv; + teamPermiable = false; + otherPermiable = false; + color = %colourOn SPC %colourOn SPC %colourOff; + powerOffColor = "0.0 0.0 0.0"; +}; + +// Team pass +datablock ForceFieldBareData(DeployedForceField7) : DeployedForceField { + baseTranslucency = %teamPassTrans; + powerOffTranslucency = %teamPassTrans / %dimDiv; + teamPermiable = true; + otherPermiable = false; + color = %colourOn SPC %colourOn SPC %colourOn; + powerOffColor = "0.0 0.0 0.0"; +}; + +datablock ForceFieldBareData(DeployedForceField8) : DeployedForceField { + baseTranslucency = %teamPassTrans; + powerOffTranslucency = %teamPassTrans / %dimDiv; + teamPermiable = true; + otherPermiable = false; + color = %colourOn SPC %colourOff SPC %colourOff; + powerOffColor = "0.0 0.0 0.0"; +}; + +datablock ForceFieldBareData(DeployedForceField9) : DeployedForceField { + baseTranslucency = %teamPassTrans; + powerOffTranslucency = %teamPassTrans / %dimDiv; + teamPermiable = true; + otherPermiable = false; + color = %colourOff SPC %colourOn SPC %colourOff; + powerOffColor = "0.0 0.0 0.0"; +}; + +datablock ForceFieldBareData(DeployedForceField10) : DeployedForceField { + baseTranslucency = %teamPassTrans; + powerOffTranslucency = %teamPassTrans / %dimDiv; + teamPermiable = true; + otherPermiable = false; + color = %colourOff SPC %colourOff SPC %colourOn; + powerOffColor = "0.0 0.0 0.0"; +}; + +datablock ForceFieldBareData(DeployedForceField11) : DeployedForceField { + baseTranslucency = %teamPassTrans; + powerOffTranslucency = %teamPassTrans / %dimDiv; + teamPermiable = true; + otherPermiable = false; + color = %colourOff SPC %colourOn SPC %colourOn; + powerOffColor = "0.0 0.0 0.0"; +}; + +datablock ForceFieldBareData(DeployedForceField12) : DeployedForceField { + baseTranslucency = %teamPassTrans; + powerOffTranslucency = %teamPassTrans / %dimDiv; + teamPermiable = true; + otherPermiable = false; + color = %colourOn SPC %colourOff SPC %colourOn; + powerOffColor = "0.0 0.0 0.0"; +}; + +datablock ForceFieldBareData(DeployedForceField13) : DeployedForceField { + baseTranslucency = %teamPassTrans; + powerOffTranslucency = %teamPassTrans / %dimDiv; + teamPermiable = true; + otherPermiable = false; + color = %colourOn SPC %colourOn SPC %colourOff; + powerOffColor = "0.0 0.0 0.0"; +}; + +// All pass +datablock ForceFieldBareData(DeployedForceField14) : DeployedForceField { + baseTranslucency = %allPassTrans; + powerOffTranslucency = %allPassTrans / %dimDiv; + teamPermiable = true; + otherPermiable = true; + color = %colourOn SPC %colourOn SPC %colourOn; + powerOffColor = "0.0 0.0 0.0"; +}; + +datablock ForceFieldBareData(DeployedForceField15) : DeployedForceField { + baseTranslucency = %allPassTrans; + powerOffTranslucency = %allPassTrans / %dimDiv; + teamPermiable = true; + otherPermiable = true; + color = %colourOn SPC %colourOff SPC %colourOff; + powerOffColor = "0.0 0.0 0.0"; +}; + +datablock ForceFieldBareData(DeployedForceField16) : DeployedForceField { + baseTranslucency = %allPassTrans; + powerOffTranslucency = %allPassTrans / %dimDiv; + teamPermiable = true; + otherPermiable = true; + color = %colourOff SPC %colourOn SPC %colourOff; + powerOffColor = "0.0 0.0 0.0"; +}; + +datablock ForceFieldBareData(DeployedForceField17) : DeployedForceField { + baseTranslucency = %allPassTrans; + powerOffTranslucency = %allPassTrans / %dimDiv; + teamPermiable = true; + otherPermiable = true; + color = %colourOff SPC %colourOff SPC %colourOn; + powerOffColor = "0.0 0.0 0.0"; +}; + +datablock ForceFieldBareData(DeployedForceField18) : DeployedForceField { + baseTranslucency = %allPassTrans; + powerOffTranslucency = %allPassTrans / %dimDiv; + teamPermiable = true; + otherPermiable = true; + color = %colourOff SPC %colourOn SPC %colourOn; + powerOffColor = "0.0 0.0 0.0"; +}; + +datablock ForceFieldBareData(DeployedForceField19) : DeployedForceField { + baseTranslucency = %allPassTrans; + powerOffTranslucency = %allPassTrans / %dimDiv; + teamPermiable = true; + otherPermiable = true; + color = %colourOn SPC %colourOff SPC %colourOn; + powerOffColor = "0.0 0.0 0.0"; +}; + +datablock ForceFieldBareData(DeployedForceField20) : DeployedForceField { + baseTranslucency = %allPassTrans; + powerOffTranslucency = %allPassTrans / %dimDiv; + teamPermiable = true; + otherPermiable = true; + color = %colourOn SPC %colourOn SPC %colourOff; + powerOffColor = "0.0 0.0 0.0"; +}; + +datablock ShapeBaseImageData(ForceFieldDeployableImage) { + mass = 1; + emap = true; + shapeFile = "ammo_chaingun.dts"; + item = ForceFieldDeployable; + mountPoint = 1; + offset = "-0.2 -0.125 0"; + rotation = "0 -1 0 90"; + deployed = DeployedForceField; + heatSignature = 0; + + stateName[0] = "Idle"; + stateTransitionOnTriggerDown[0] = "Activate"; + + stateName[1] = "Activate"; + stateScript[1] = "onActivate"; + stateTransitionOnTriggerUp[1] = "Idle"; + + maxDepSlope = 360; + deploySound = ItemPickupSound; + + minDeployDis = 0.1; + maxDeployDis = 50.0; +}; + +datablock ItemData(ForceFieldDeployable) { + className = Pack; + catagory = "Deployables"; + shapeFile = "stackable1s.dts"; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 1; + rotate = true; + image = "ForceFieldDeployableImage"; + pickUpName = "a force field pack"; + heatSignature = 0; + emap = true; +}; + +function ForceFieldDeployableImage::testObjectTooClose(%item) { + return; +} + +function ForceFieldDeployableImage::testNoTerrainFound(%item) { + // don't check this for non-Landspike turret deployables +} + +function ForceFieldDeployable::onPickup(%this, %obj, %shape, %amount) { + // created to prevent console errors +} + +function ForceFieldDeployableImage::onDeploy(%item, %plyr, %slot) { + //Object + %className = "ForceFieldBare"; + + %grounded = 0; + if (%item.surface.getClassName() $= TerrainBlock) + %grounded = 1; + + %playerVector = vectorNormalize(-1 * getWord(%plyr.getEyeVector(),1) SPC getWord(%plyr.getEyeVector(),0) SPC "0"); + + if (%item.surfaceinher == 0) { + if (vAbs(floorVec(%item.surfaceNrm,100)) $= "0 0 1") + %item.surfaceNrm2 = %playerVector; + else + %item.surfaceNrm2 = vectorNormalize(vectorCross(%item.surfaceNrm,"0 0 1")); + } + + %rot = fullRot(%item.surfaceNrm,%item.surfaceNrm2); + %scale = getWords($packSetting["forcefield",%plyr.packSet],0,2); + %mCenter = "-0.5 -0.5 -0.5"; + %pad = pad(%item.surfacePt SPC %item.surfaceNrm SPC %item.surfaceNrm2,%scale,%mCenter); + %scale = getWords(%pad,0,2); + %item.surfacePt = getWords(%pad,3,5); + %rot = getWords(%pad,6,9); + + // Add padding + %padSize = 0.01; + %scale = vectorAdd(%scale,%padSize * 2 SPC %padSize * 2 SPC -%padSize * 2); + %item.surfacePt = vectorSub(%item.surfacePt,vectorScale(vectorNormalize(%item.surfaceNrm),%padSize)); + %item.surfacePt = vectorSub(%item.surfacePt,vectorScale(vectorNormalize(%item.surfaceNrm2),%padSize)); + %item.surfacePt = vectorSub(%item.surfacePt,vectorScale(vectorNormalize(vectorCross(%item.surfaceNrm,%item.surfaceNrm2)),-%padSize)); + + if ($Host::ExpertMode == 1) { + if (isCubic(%item.surface) && (%plyr.expertSet == 1 || %plyr.expertSet == 3) && %plyr.team == %item.surface.team + && %item.surface.getType() & $TypeMasks::StaticShapeObjectType + && (($Host::OnlyOwnerCubicReplace == 0) || (%plyr.client == %item.surface.getOwner()))) { + %scale = vectorAdd(realSize(%item.surface),%padSize * 2 SPC %padSize * 2 SPC %padSize * 2); + %center = realVec(%item.surface,vectorScale(getWords(%scale,0,1) SPC "0",-0.5)); + %item.surfacePt = vectorAdd(pos(%item.surface),%center); + %rot = rot(%item.surface); + %mod = vectorScale(matrixMulVector("0 0 0" SPC %rot ,"0 0 1"),-%padSize); + %item.surfacePt = vectorAdd(%item.surfacePt,%mod); + %item.surface.getDataBlock().disassemble(%plyr, %item.surface); + } + } + + // TODO - temporary test fix - remove? + %scale = vectorAdd(%scale,"0 0 0"); + %x = getWord(%scale,0); + %y = getWord(%scale,1); + %z = getWord(%scale,2); + if (%x <= 0) + %x = 0.001; + if (%y <= 0) + %y = 0.001; + if (%z <= 0) + %z = 0.001; + %scale = %x SPC %y SPC %z; + + %deplObj = new (%className)() { + dataBlock = %item.deployed @ %plyr.packSet; + scale = %scale; + }; + + // Take the deployable off the player's back and out of inventory + if ($Host::ExpertMode == 0) { + %plyr.unMountImage(%slot); + %plyr.decInventory(%item.item,1); + } + +////////////////////////Apply settings////////////////////////////// + + // [[Location]]: + + // exact: + %deplObj.setTransform(%item.surfacePt SPC %rot); + %deplObj.pzone.setTransform(%item.surfacePt SPC %rot); + + if ($Host::ExpertMode == 1) { + if (%plyr.expertSet == 2 || %plyr.expertSet == 3) { + %deplObj.noSlow = true; + %deplObj.pzone.delete(); + %deplObj.pzone = ""; + } + } + + // misc info + addDSurface(%item.surface,%deplObj); + + // [[Settings]]: + + %deplObj.grounded = %grounded; + %deplObj.needsFit = 1; + + // [[Normal Stuff]]: + + // set team, owner, and handle + %deplObj.team = %plyr.client.team; + %deplObj.setOwner(%plyr); + + // set power frequency + %deplObj.powerFreq = %plyr.powerFreq; + + // set the sensor group if it needs one + if (%deplObj.getTarget() != -1) + setTargetSensorGroup(%deplObj.getTarget(), %plyr.client.team); + + // place the deployable in the MissionCleanup/Deployables group (AI reasons) + addToDeployGroup(%deplObj); + + //let the AI know as well... + AIDeployObject(%plyr.client, %deplObj); + + // play the deploy sound + serverPlay3D(%item.deploySound, %deplObj.getTransform()); + + // increment the team count for this deployed object + $TeamDeployedCount[%plyr.team, %item.item]++; + + // Power object + checkPowerObject(%deplObj); + + if (!%deplObj.powerCount > 0) { + %deplObj.getDataBlock().disassemble(0,%deplObj); // Run Item Specific code. + messageClient(%plyr.client,'MsgDeployFailed','\c2Force field lost - no power source found!%1','~wfx/misc/misc.error.wav'); + } + + return %deplObj; +} + +///////////////////////////////////// + +function ForceFieldDeployableImage::onMount(%data, %obj, %node) { + %obj.hasForceField = true; // set for forcefieldcheck + %obj.packSet = 0; + %obj.expertSet = 0; + displayPowerFreq(%obj); +} + +function ForceFieldDeployableImage::onUnmount(%data, %obj, %node) { + %obj.hasForceField = ""; + %obj.packSet = 0; + %obj.expertSet = 0; +} + +function DeployedForceField::disassemble(%data,%plyr,%obj) { + if (isObject(%obj.pzone)) + %obj.pzone.delete(); + disassemble(%data,%plyr,%obj); +} + +function DeployedForceField0::disassemble(%data,%plyr,%obj) { + DeployedForceField::disassemble(%data,%plyr,%obj); +} + +function DeployedForceField1::disassemble(%data,%plyr,%obj) { + DeployedForceField::disassemble(%data,%plyr,%obj); +} + +function DeployedForceField2::disassemble(%data,%plyr,%obj) { + DeployedForceField::disassemble(%data,%plyr,%obj); +} + +function DeployedForceField3::disassemble(%data,%plyr,%obj) { + DeployedForceField::disassemble(%data,%plyr,%obj); +} + +function DeployedForceField4::disassemble(%data,%plyr,%obj) { + DeployedForceField::disassemble(%data,%plyr,%obj); +} + +function DeployedForceField5::disassemble(%data,%plyr,%obj) { + DeployedForceField::disassemble(%data,%plyr,%obj); +} + +function DeployedForceField6::disassemble(%data,%plyr,%obj) { + DeployedForceField::disassemble(%data,%plyr,%obj); +} + +function DeployedForceField7::disassemble(%data,%plyr,%obj) { + DeployedForceField::disassemble(%data,%plyr,%obj); +} + +function DeployedForceField8::disassemble(%data,%plyr,%obj) { + DeployedForceField::disassemble(%data,%plyr,%obj); +} + +function DeployedForceField9::disassemble(%data,%plyr,%obj) { + DeployedForceField::disassemble(%data,%plyr,%obj); +} + +function DeployedForceField10::disassemble(%data,%plyr,%obj) { + DeployedForceField::disassemble(%data,%plyr,%obj); +} + +function DeployedForceField11::disassemble(%data,%plyr,%obj) { + DeployedForceField::disassemble(%data,%plyr,%obj); +} + +function DeployedForceField12::disassemble(%data,%plyr,%obj) { + DeployedForceField::disassemble(%data,%plyr,%obj); +} + +function DeployedForceField13::disassemble(%data,%plyr,%obj) { + DeployedForceField::disassemble(%data,%plyr,%obj); +} + +function DeployedForceField14::disassemble(%data,%plyr,%obj) { + DeployedForceField::disassemble(%data,%plyr,%obj); +} + +function DeployedForceField15::disassemble(%data,%plyr,%obj) { + DeployedForceField::disassemble(%data,%plyr,%obj); +} + +function DeployedForceField16::disassemble(%data,%plyr,%obj) { + DeployedForceField::disassemble(%data,%plyr,%obj); +} + +function DeployedForceField17::disassemble(%data,%plyr,%obj) { + DeployedForceField::disassemble(%data,%plyr,%obj); +} + +function DeployedForceField18::disassemble(%data,%plyr,%obj) { + DeployedForceField::disassemble(%data,%plyr,%obj); +} + +function DeployedForceField19::disassemble(%data,%plyr,%obj) { + DeployedForceField::disassemble(%data,%plyr,%obj); +} + +function DeployedForceField20::disassemble(%data,%plyr,%obj) { + DeployedForceField::disassemble(%data,%plyr,%obj); +} diff --git a/scripts/packs/generator.cs b/scripts/packs/generator.cs new file mode 100644 index 0000000..2ae853e --- /dev/null +++ b/scripts/packs/generator.cs @@ -0,0 +1,145 @@ +//-------------------------------------------------------------------------- +// Deployable Generator +//-------------------------------------------------------------------------- + +datablock ShapeBaseImageData(GeneratorDeployableImage) { + mass = 1; + emap = true; + shapeFile = "stackable1s.dts"; + item = GeneratorDeployable; + mountPoint = 1; + offset = "0 0 0"; + deployed = GeneratorLarge; + heatSignature = 0; + + stateName[0] = "Idle"; + stateTransitionOnTriggerDown[0] = "Activate"; + + stateName[1] = "Activate"; + stateScript[1] = "onActivate"; + stateTransitionOnTriggerUp[1] = "Idle"; + + isLarge = true; + maxDepSlope = 360; + deploySound = ItemPickupSound; + + minDeployDis = 2; + maxDeployDis = 5; +}; + +datablock ItemData(GeneratorDeployable) { + className = Pack; + catagory = "Deployables"; + shapeFile = "stackable1s.dts"; + mass = 1; + + hasLight = true; + lightType = "PulsingLight"; + lightColor = "0.1 0.8 0.8 1.0"; + lightTime = "1000"; + lightRadius = "3"; + + elasticity = 0.2; + friction = 0.6; + pickupRadius = 3; + rotate = true; + image = "GeneratorDeployableImage"; + pickUpName = "a generator pack"; + heatSignature = 0; + emap = true; +}; + +function GeneratorDeployableImage::testNoTerrainFound(%item) { + // don't check this for non-Landspike turret deployables +} + +function GeneratorDeployable::onPickup(%this, %obj, %shape, %amount) { + // created to prevent console errors +} + +function GeneratorDeployableImage::onDeploy(%item, %plyr, %slot) { + %className = "StaticShape"; + + %playerVector = vectorNormalize(getWord(%plyr.getEyeVector(),1) SPC -1 * getWord(%plyr.getEyeVector(),0) SPC "0"); + + if (vAbs(floorVec(%item.surfaceNrm,100)) $= "0 0 1") + %item.surfaceNrm2 = vectorScale(%playerVector,-1); + else + %item.surfaceNrm2 = vectorNormalize(vectorCross(%item.surfaceNrm,"0 0 1")); + + %rot = fullRot(%item.surfaceNrm,%item.surfaceNrm2); + + %item.surfacePt = vectorAdd(%item.surfacePt,vectorScale(vectorNormalize(vectorCross(%item.surfaceNrm,%item.surfaceNrm2)),2)); + + %deplObj = new (%className)() { + dataBlock = GeneratorLarge; + deployed = true; + }; + + // set orientation + %deplObj.setTransform(%item.surfacePt SPC %rot); + + // set team, owner, and handle + %deplObj.team = %plyr.client.Team; + %deplObj.setOwner(%plyr); + + // set power frequency + %deplObj.powerFreq = %plyr.powerFreq; + setTargetName(%deplObj.target,addTaggedString("Frequency" SPC %deplObj.powerFreq)); + + // set power + %deplObj.setSelfPowered(); + + // set the sensor group if it needs one + if (%deplObj.getTarget() != -1) + setTargetSensorGroup(%deplObj.getTarget(), %plyr.client.team); + + // place the deployable in the MissionCleanup/Deployables group (AI reasons) + addToDeployGroup(%deplObj); + + //let the AI know as well... + AIDeployObject(%plyr.client, %deplObj); + + // play the deploy sound + serverPlay3D(%item.deploySound, %deplObj.getTransform()); + + // increment the team count for this deployed object + $TeamDeployedCount[%plyr.team, %item.item]++; + + addDSurface(%item.surface,%deplObj); + + %deplObj.playThread($PowerThread,"Power"); + + // take the deployable off the player's back and out of inventory + %plyr.unmountImage(%slot); + %plyr.decInventory(%item.item, 1); + + // add to power list + $PowerList = listAdd($PowerList,%deplObj,-1); + + return %deplObj; +} + +function GeneratorLarge::onDestroyed(%this,%obj,%prevState) { + if (%obj.isRemoved) + return; + if (%obj.deployed && ($Host::InvincibleDeployables != 1 || %obj.damageFailedDecon)) { + %obj.isRemoved = true; + %loc = findWord($PowerList,%obj); + if (%loc !$= "") + $PowerList = listDel($PowerList,%loc); + $TeamDeployedCount[%obj.team,GeneratorDeployable]--; + remDSurface(%obj); + %obj.schedule(500,"delete"); + } + Parent::onDestroyed(%data,%obj,%prevState); +} + +function GeneratorDeployableImage::onMount(%data,%obj,%node) { + %obj.hasGen = true; // set for gencheck + displayPowerFreq(%obj); +} + +function GeneratorDeployableImage::onUnmount(%data,%obj,%node) { + %obj.hasGen = ""; +} diff --git a/scripts/packs/gravityfieldpack.cs b/scripts/packs/gravityfieldpack.cs new file mode 100644 index 0000000..6f0d34b --- /dev/null +++ b/scripts/packs/gravityfieldpack.cs @@ -0,0 +1,344 @@ +//--------------------------------------------------------- +// Deployable Gravity Field +//--------------------------------------------------------- + +// Translucencies +%fieldTrans = 1.0; +%powerOffTrans = 0.25; + +// RGB +%colourOn = 0.6; +%colourOff = 0.15; +%dimDiv = 3; + +datablock ForceFieldBareData(DeployedGravityField) { + className = "gravityfield"; + fadeMS = 1000; + baseTranslucency = %fieldTrans; + powerOffTranslucency = %powerOffTrans; + teamPermiable = true; + otherPermiable = true; + color = "1.0 1.0 1.0"; + powerOffColor = "0.0 0.0 0.0"; + targetTypeTag = 'GravityField'; + texture[0] = "skins/forcef1"; + texture[1] = "skins/forcef2"; + texture[2] = "skins/forcef3"; + texture[3] = "skins/forcef4"; + texture[4] = "skins/forcef5"; + framesPerSec = 10; + numFrames = 5; + scrollSpeed = 15; + umapping = 1.0; + vmapping = 0.15; + deployedFrom = GravityFieldDeployable; + velocityMod = 1; + gravityMod = 1; + appliedForce = "0 0 0"; + needsPower = true; +}; + +// slow +datablock ForceFieldBareData(DeployedGravityField0) : DeployedGravityField { + baseTranslucency = %fieldTrans; + powerOffTranslucency = %powerOffTrans; + teamPermiable = true; + otherPermiable = true; + color = %colourOff/%dimDiv SPC %colourOn/%dimDiv SPC %colourOff/%dimDiv; + powerOffColor = "0.0 0.0 0.0"; + velocityMod = 1; + gravityMod = 0; +}; + +// fast +datablock ForceFieldBareData(DeployedGravityField1) : DeployedGravityField { + baseTranslucency = %fieldTrans; + powerOffTranslucency = %powerOffTrans; + teamPermiable = true; + otherPermiable = true; + color = %colourOff SPC %colourOn SPC %colourOff; + powerOffColor = "0.0 0.0 0.0"; + velocityMod = 1; + gravityMod = 0; +}; + +// zero gravity +datablock ForceFieldBareData(DeployedGravityField2) : DeployedGravityField { + baseTranslucency = %fieldTrans; + powerOffTranslucency = %powerOffTrans; + teamPermiable = true; + otherPermiable = true; + color = %colourOn SPC %colourOn SPC %colourOff; + powerOffColor = "0.0 0.0 0.0"; + velocityMod = 1; + gravityMod = 0; +}; + +// fastfield +datablock ForceFieldBareData(DeployedGravityField3) : DeployedGravityField { + baseTranslucency = %fieldTrans; + powerOffTranslucency = %powerOffTrans; + teamPermiable = true; + otherPermiable = true; + color = %colourOn/%dimDiv SPC %colourOff/%dimDiv SPC %colourOn/%dimDiv; + powerOffColor = "0.0 0.0 0.0"; + velocityMod = 1.5; + gravityMod = 0; +}; + +// super fastfield +datablock ForceFieldBareData(DeployedGravityField4) : DeployedGravityField { + baseTranslucency = %fieldTrans; + powerOffTranslucency = %powerOffTrans; + teamPermiable = true; + otherPermiable = true; + color = %colourOn SPC %colourOff SPC %colourOn; + powerOffColor = "0.0 0.0 0.0"; + velocityMod = 1.7; + gravityMod = 0; +}; + +datablock ShapeBaseImageData(GravityFieldDeployableImage) { + mass = 1; + emap = true; + shapeFile = "ammo_chaingun.dts"; + item = GravityFieldDeployable; + mountPoint = 1; + offset = "-0.2 -0.125 0"; + rotation = "0 -1 0 90"; + deployed = DeployedGravityField; + heatSignature = 0; + + stateName[0] = "Idle"; + stateTransitionOnTriggerDown[0] = "Activate"; + + stateName[1] = "Activate"; + stateScript[1] = "onActivate"; + stateTransitionOnTriggerUp[1] = "Idle"; + + maxDepSlope = 360; + deploySound = ItemPickupSound; + + minDeployDis = 0.1; + maxDeployDis = 50.0; +}; + +datablock ItemData(GravityFieldDeployable) { + className = Pack; + catagory = "Deployables"; + shapeFile = "stackable1s.dts"; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 1; + joint = "4.75 4.75 4.75"; + rotate = true; + image = "GravityFieldDeployableImage"; + pickUpName = "a gravity field pack"; + heatSignature = 0; + emap = true; +}; + +function GravityFieldDeployableImage::testObjectTooClose(%item) { + return; +} + +function GravityFieldDeployableImage::testNoTerrainFound(%item) { + // don't check this for non-Landspike turret deployables +} + +function GravityFieldDeployable::onPickup(%this, %obj, %shape, %amount) { + // created to prevent console errors +} + +function GravityFieldDeployableImage::onDeploy(%item, %plyr, %slot) { + //Object + %className = "ForceFieldBare"; + + %grounded = 0; + if (%item.surface.getClassName() $= TerrainBlock) + %grounded = 1; + + %playerVector = vectorNormalize(-1 * getWord(%plyr.getEyeVector(),1) SPC getWord(%plyr.getEyeVector(),0) SPC "0"); + + if (%item.surfaceinher == 0) { + if (vAbs(floorVec(%item.surfaceNrm,100)) $= "0 0 1") + %item.surfaceNrm2 = %playerVector; + else + %item.surfaceNrm2 = vectorNormalize(vectorCross(%item.surfaceNrm,"0 0 1")); + } + + %rot = fullRot(%item.surfaceNrm,%item.surfaceNrm2); + %scale = getWords($packSetting["gravfield",%plyr.packSet],0,2); + + %space = rayDist(%item.surfacePt SPC %item.surfaceNrm,%scale); + %scale = getWord(%scale,0) SPC getWord(%scale,0) SPC %space; + + // Shift field position since field handle is not field center + %mod = firstWord($packSetting["gravfield",%plyr.packSet]) / 2; + %item.surfacePt = vectorSub(%item.surfacePt,vectorScale(vectorNormalize(%item.surfaceNrm2),%mod)); + %item.surfacePt = vectorSub(%item.surfacePt,vectorScale(vectorNormalize(vectorCross(%item.surfaceNrm,%item.surfaceNrm2)),%mod)); + + // Add padding + %padSize = 0.01; + %scale = vectorAdd(%scale,%padSize * 2 SPC %padSize * 2 SPC %padSize * 2); + %item.surfacePt = vectorSub(%item.surfacePt,vectorScale(vectorNormalize(%item.surfaceNrm),%padSize)); + %item.surfacePt = vectorSub(%item.surfacePt,vectorScale(vectorNormalize(%item.surfaceNrm2),%padSize)); + %item.surfacePt = vectorSub(%item.surfacePt,vectorScale(vectorNormalize(vectorCross(%item.surfaceNrm,%item.surfaceNrm2)),%padSize)); + + // Set datablock + if (%plyr.packSet == 0) + %dataBlock = nameToID(%item.deployed @ 0); + else if (%plyr.packSet == 1) + %dataBlock = nameToID(%item.deployed @ 1); + else if (%plyr.packSet == 2) + %dataBlock = nameToID(%item.deployed @ 0); + else if (%plyr.packSet == 3) + %dataBlock = nameToID(%item.deployed @ 1); + else if (%plyr.packSet == 4) + %dataBlock = nameToID(%item.deployed @ 2); + else if (%plyr.packSet == 5) + %dataBlock = nameToID(%item.deployed @ 3); + else if (%plyr.packSet == 6) + %dataBlock = nameToID(%item.deployed @ 4); + + %appliedForceVec = vectorNormalize(%item.surfaceNrm); + + if ($Host::ExpertMode == 1) { + if (isCubic(%item.surface) && (%plyr.expertSet == 1 || %plyr.expertSet == 2) && %plyr.team == %item.surface.team + && %item.surface.getType() & $TypeMasks::StaticShapeObjectType + && (($Host::OnlyOwnerCubicReplace == 0) || (%plyr.client == %item.surface.getOwner()))) { + if (%plyr.expertSet == 2) + %appliedForceVec = vectorNormalize(realVec(%item.surface,"0 0 1")); + %scale = vectorAdd(realSize(%item.surface),%padSize * 2 SPC %padSize * 2 SPC %padSize * 2); + %center = realVec(%item.surface,vectorScale(getWords(%scale,0,1) SPC "0",-0.5)); + %item.surfacePt = vectorAdd(pos(%item.surface),%center); + %rot = rot(%item.surface); + %mod = vectorScale(matrixMulVector("0 0 0" SPC %rot ,"0 0 1"),-%padSize); + %item.surfacePt = vectorAdd(%item.surfacePt,%mod); + %item.surface.getDataBlock().disassemble(%plyr, %item.surface); + } + } + + %velocityMod = %dataBlock.velocityMod; + %gravityMod = %dataBlock.gravityMod; + %appliedForce = %dataBlock.appliedForce; + + %slowForce = 500; + %fastForce = 1000; + + if (%plyr.packSet == 0) + %appliedForce = vectorScale(%appliedForceVec,%slowForce); + else if (%plyr.packSet == 1) + %appliedForce = vectorScale(%appliedForceVec,%fastForce); + else if (%plyr.packSet == 2) + %appliedForce = vectorScale(%appliedForceVec,-%slowForce); + else if (%plyr.packSet == 3) + %appliedForce = vectorScale(%appliedForceVec,-%fastForce); + + %deplObj = new (%className)() { + dataBlock = %dataBlock; + scale = %scale; + velocityMod = %velocityMod; + gravityMod = %gravityMod; + appliedForce = %appliedForce; + }; + + // Take the deployable off the player's back and out of inventory + if ($Host::ExpertMode == 0) { + %plyr.unMountImage(%slot); + %plyr.decInventory(%item.item,1); + } + +////////////////////////Apply settings////////////////////////////// + + // [[Location]]: + + // exact: + %deplObj.setTransform(%item.surfacePt SPC %rot); + %deplObj.pzone.setTransform(%item.surfacePt SPC %rot); + + // misc info + addDSurface(%item.surface,%deplObj); + + // [[Settings]]: + + %deplObj.grounded = %grounded; + %deplObj.needsFit = 1; + + // [[Normal Stuff]]: + + // set team, owner, and handle + %deplObj.team = %plyr.client.team; + %deplObj.setOwner(%plyr); + + // set power frequency + %deplObj.powerFreq = %plyr.powerFreq; + + // set the sensor group if it needs one + if (%deplObj.getTarget() != -1) + setTargetSensorGroup(%deplObj.getTarget(), %plyr.client.team); + + // place the deployable in the MissionCleanup/Deployables group (AI reasons) + addToDeployGroup(%deplObj); + + //let the AI know as well... + AIDeployObject(%plyr.client, %deplObj); + + // play the deploy sound + serverPlay3D(%item.deploySound, %deplObj.getTransform()); + + // increment the team count for this deployed object + $TeamDeployedCount[%plyr.team, %item.item]++; + + // Power object + checkPowerObject(%deplObj); + + if (!%deplObj.powerCount > 0) { + %deplObj.getDataBlock().disassemble(0,%deplObj); // Run Item Specific code. + messageClient(%plyr.client,'MsgDeployFailed','\c2Gravity field lost - no power source found!%1','~wfx/misc/misc.error.wav'); + } + + return %deplObj; +} + +///////////////////////////////////// + +function GravityFieldDeployableImage::onMount(%data, %obj, %node) { + %obj.hasGravField = true; // set for gravfieldcheck + %obj.packSet = 0; + %obj.expertSet = 0; + displayPowerFreq(%obj); +} + +function GravityFieldDeployableImage::onUnmount(%data, %obj, %node) { + %obj.hasGravField = ""; + %obj.packSet = 0; + %obj.expertSet = 0; +} + +function DeployedGravityField::disassemble(%data,%plyr,%obj) { + if (isObject(%obj.pzone)) + %obj.pzone.delete(); + disassemble(%data,%plyr,%obj); +} + +function DeployedGravityField0::disassemble(%data,%plyr,%obj) { + DeployedGravityField::disassemble(%data,%plyr,%obj); +} + +function DeployedGravityField1::disassemble(%data,%plyr,%obj) { + DeployedGravityField::disassemble(%data,%plyr,%obj); +} + +function DeployedGravityField2::disassemble(%data,%plyr,%obj) { + DeployedGravityField::disassemble(%data,%plyr,%obj); +} + +function DeployedGravityField3::disassemble(%data,%plyr,%obj) { + DeployedGravityField::disassemble(%data,%plyr,%obj); +} + +function DeployedGravityField4::disassemble(%data,%plyr,%obj) { + DeployedGravityField::disassemble(%data,%plyr,%obj); +} diff --git a/scripts/packs/jumpad.cs b/scripts/packs/jumpad.cs new file mode 100644 index 0000000..6d263f2 --- /dev/null +++ b/scripts/packs/jumpad.cs @@ -0,0 +1,176 @@ +//-------------------------------------------------------------------------- +// Jumpad +//-------------------------------------------------------------------------- + +datablock StaticShapeData(DeployedJumpad) : StaticShapeDamageProfile { + className = "jumpad"; + shapeFile = "nexusbase.dts"; // dmiscf.dts, alternate + maxDamage = 2.0; + destroyedLevel = 2.0; + disabledLevel = 2.0; + mass = 1; + elasticity = 0.1; + friction = 0.9; + collideable = 1; + pickupRadius = 1; + sticky=false; + + impulse = 5000; + + hasLight = true; + lightType = "PulsingLight"; + lightColor = "0.1 0.8 0.8 1.0"; + lightTime = "100"; + lightRadius = "3"; + + explosion = HandGrenadeExplosion; + expDmgRadius = 3.0; + expDamage = 0.1; + expImpulse = 200.0; + dynamicType = $TypeMasks::StaticShapeObjectType; + deployedObject = true; + cmdCategory = "DSupport"; + cmdIcon = CMDSensorIcon; + cmdMiniIconName = "commander/MiniIcons/com_deploymotionsensor"; + + targetNameTag = 'Jump'; + targetTypeTag = 'Pad'; + deployAmbientThread = true; + debrisShapeName = "debris_generic_small.dts"; + debris = DeployableDebris; + heatSignature = 0; +}; + +datablock ShapeBaseImageData(JumpadDeployableImage) { + mass = 1; + emap = true; + shapeFile = "stackable1s.dts"; + item = JumpadDeployable; + mountPoint = 1; + offset = "0 0 0"; + deployed = DeployedJumpad; + heatSignature = 0; + collideable = 1; + stateName[0] = "Idle"; + stateTransitionOnTriggerDown[0] = "Activate"; + + stateName[1] = "Activate"; + stateScript[1] = "onActivate"; + stateTransitionOnTriggerUp[1] = "Idle"; + + isLarge = true; + maxDepSlope = 360; // 30 + deploySound = ItemPickupSound; + + minDeployDis = 0.5; + maxDeployDis = 5.0; +}; + +datablock ItemData(JumpadDeployable) { + className = Pack; + catagory = "Deployables"; + shapeFile = "stackable1s.dts"; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 1; + rotate = true; + image = "JumpadDeployableImage"; + pickUpName = "a jump pad pack"; + heatSignature = 0; + emap = true; +}; + +function JumpadDeployable::onPickup(%this, %obj, %shape, %amount) { + // created to prevent console errors +} + +function JumpadDeployableImage::onDeploy(%item, %plyr, %slot) { + %className = "StaticShape"; + + %playerVector = vectorNormalize(-1 * getWord(%plyr.getEyeVector(),1) SPC getWord(%plyr.getEyeVector(),0) SPC "0"); + + if (vAbs(floorVec(%item.surfaceNrm,100)) $= "0 0 1") + %item.surfaceNrm2 = %playerVector; + else + %item.surfaceNrm2 = vectorNormalize(vectorCross(%item.surfaceNrm,"0 0 -1")); + + %impulse = firstWord($packSetting["jumpad",%plyr.packSet]); + + %deplObj = new (%className)() { + dataBlock = %item.deployed; + scale = "1 1 2"; + }; + + // set impulse (jump pad strength) + %deplObj.impulse = %impulse; + + // set orientation + %deplObj.setDeployRotation(getWords(%item.surfacePt, 0, 1) SPC getWord(%item.surfacePt, 2) + 0.1, %item.surfaceNrm); + + // set the recharge rate right away + if (%deplObj.getDatablock().rechargeRate) + %deplObj.setRechargeRate(%deplObj.getDatablock().rechargeRate); + + // set team, owner, and handle + %deplObj.team = %plyr.client.Team; + %deplObj.setOwner(%plyr); + + // place the deployable in the MissionCleanup/Deployables group (AI reasons) + addToDeployGroup(%deplObj); + + //let the AI know as well... + AIDeployObject(%plyr.client, %deplObj); + + // play the deploy sound + serverPlay3D(%item.deploySound, %deplObj.getTransform()); + + // increment the team count for this deployed object + + // take the deployable off the player's back and out of inventory + %plyr.unmountImage(%slot); + %plyr.decInventory(%item.item, 1); + + $TeamDeployedCount[%plyr.team, %item.item]++; + + addDSurface(%item.surface,%deplObj); + return %deplObj; +} + +function DeployedJumpad::onCollision(%data,%obj,%col) { + // TODO - update escape pod + if (%col.getClassName() !$= "Player" && %col.getDataBlock().getName() !$= "EscapePodVehicle") + return; // Only boost players + if (%obj.team == %col.team) { + %vel = %col.getVelocity(); + %vec = realVec(%obj,"0 0 1"); + %position = getWords(%col.getTransform(), 0, 2); +// %impulseVec = vectorScale(%vec,1000); // Jump clear of the pad +// %col.applyImpulse(%position, %impulseVec); + %col.playAudio(0, MortarFireSound); + %impulseVec = vectorScale(%vec,%obj.impulse); +// %col.schedule(50, "applyImpulse", %position, %impulseVec); + %col.applyImpulse(%position, %impulseVec); + } +} + +function DeployedJumpad::onDestroyed(%this, %obj, %prevState) { + if (%obj.isRemoved) + return; + %obj.isRemoved = true; + Parent::onDestroyed(%this, %obj, %prevState); + $TeamDeployedCount[%obj.team, JumpadDeployable]--; + remDSurface(%obj); + %obj.schedule(500, "delete"); + fireBallExplode(%obj,1); +} + +function JumpadDeployableImage::onMount(%data, %obj, %node) { + %obj.hasJumpad = true; // set for jumpadcheck + %obj.packSet = 0; +} + +function JumpadDeployableImage::onUnmount(%data, %obj, %node) { + %obj.hasJumpad = ""; + %obj.packSet = 0; +} diff --git a/scripts/packs/largeInventory.cs b/scripts/packs/largeInventory.cs new file mode 100644 index 0000000..bfc3cdd --- /dev/null +++ b/scripts/packs/largeInventory.cs @@ -0,0 +1,123 @@ +//-------------------------------------------------------------------------- +// Large Inventory Station +// +// +//-------------------------------------------------------------------------- + +datablock ShapeBaseImageData(LargeInventoryDeployableImage) { + mass = 1; + emap = true; + shapeFile = "stackable1s.dts"; + item = LargeInventoryDeployable; + mountPoint = 1; + offset = "0 0 0"; + deployed = StationInventory; + heatSignature = 0; + + stateName[0] = "Idle"; + stateTransitionOnTriggerDown[0] = "Activate"; + + stateName[1] = "Activate"; + stateScript[1] = "onActivate"; + stateTransitionOnTriggerUp[1] = "Idle"; + + isLarge = true; + maxDepSlope = 360; + deploySound = ItemPickupSound; + + minDeployDis = 0.5; + maxDeployDis = 5.0; +}; + +datablock ItemData(LargeInventoryDeployable) +{ + className = Pack; + catagory = "Deployables"; + shapeFile = "stackable1s.dts"; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 1; + rotate = true; + image = "LargeInventoryDeployableImage"; + joint = "4.5 4.5 4.5"; + pickUpName = "a large inventory station pack"; + heatSignature = 0; + emap = true; +}; + +function LargeInventoryDeployable::onPickup(%this, %obj, %shape, %amount) +{ + // created to prevent console errors +} + +function LargeInventoryDeployableImage::onDeploy(%item, %plyr, %slot) { + %className = "StaticShape"; + %plyr.unMountImage(%slot); + %plyr.decInventory(%item.item,1); + %grounded = 0; + if (%item.surface.getClassName() $= TerrainBlock) + %grounded = 1; + + %playerVector = vectorNormalize(-1 * getWord(%plyr.getEyeVector(),1) SPC getWord(%plyr.getEyeVector(),0) SPC "0"); + + if (vAbs(floorVec(%item.surfaceNrm,100)) $= "0 0 1") + %item.surfaceNrm2 = vectorScale(%playerVector,-1); + else + %item.surfaceNrm2 = vectorNormalize(vectorCross(%item.surfaceNrm,"0 0 1")); + + %rot = fullRot(%item.surfaceNrm,%item.surfaceNrm2); + + %deplObj = new (%className)() //Inventory Station + { + dataBlock = StationInventory; + position = %surfacePt; + rotation = %rot; + deployed = true; + }; + %deplObj.setTransform(%item.surfacePt SPC %rot); + + %deplObj.team = %plyr.client.Team; + %deplObj.setOwner(%plyr); + addDSurface(%item.surface,%deplObj); + + // set power frequency + %deplObj.powerFreq = %plyr.powerFreq; + + if(%deplObj.getTarget() != -1) + setTargetSensorGroup(%deplObj.getTarget(), %plyr.client.team); + + // place the deployable in the MissionCleanup/Deployables group (AI reasons) + + addToDeployGroup(%deplObj); + + //let the AI know as well... + + AIDeployObject(%plyr.client, %deplObj); + + // play the deploy sound + serverPlay3D(%item.deploySound, %deplObj.getTransform()); + + // increment the team count for this deployed object + + $TeamDeployedCount[%plyr.team, %item.item]++; + + %deplObj.deploy(); + + // Adjust the trigger object + adjustTrigger(%deplObj); + + // Power object + checkPowerObject(%deplObj); + + return %deplObj; +} + +function LargeInventoryDeployableImage::testNoTerrainFound(%item) +{ +//return %item.surface.getClassName() !$= TerrainBlock; +} + +function LargeInventoryDeployableImage::onMount(%data, %obj, %node) { + displayPowerFreq(%obj); +} diff --git a/scripts/packs/largeSensor.cs b/scripts/packs/largeSensor.cs new file mode 100644 index 0000000..6e6576d --- /dev/null +++ b/scripts/packs/largeSensor.cs @@ -0,0 +1,127 @@ +//-------------------------------------------------------------------------- +// Large Pulse Sensor +//-------------------------------------------------------------------------- + +datablock ShapeBaseImageData(LargeSensorDeployableImage) { + mass = 1; + emap = true; + shapeFile = "stackable1s.dts"; + item = LargeSensorDeployable; + mountPoint = 1; + offset = "0 0 0"; + deployed = SensorLargePulse; + heatSignature = 0; + + stateName[0] = "Idle"; + stateTransitionOnTriggerDown[0] = "Activate"; + + stateName[1] = "Activate"; + stateScript[1] = "onActivate"; + stateTransitionOnTriggerUp[1] = "Idle"; + + isLarge = true; + maxDepSlope = 360; + deploySound = ItemPickupSound; + + minDeployDis = 0.5; + maxDeployDis = 5.0; +}; + +datablock ItemData(LargeSensorDeployable) { + className = Pack; + catagory = "Deployables"; + shapeFile = "stackable1s.dts"; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 1; + rotate = true; + image = "LargeSensorDeployableImage"; + joint = "4.5 4.5 4.5"; + pickUpName = "a large pulse sensor pack"; + heatSignature = 0; + emap = true; +}; + +function LargeSensorDeployable::onPickup(%this, %obj, %shape, %amount) { + // created to prevent console errors +} + +function LargeSensorDeployableImage::testNoTerrainFound(%item) { + // don't check this for non-Landspike turret deployables +} + +function LargeSensorDeployableImage::onDeploy(%item, %plyr, %slot) { + %className = "StaticShape"; + + %playerVector = vectorNormalize(getWord(%plyr.getEyeVector(),1) SPC -1 * getWord(%plyr.getEyeVector(),0) SPC "0"); + %item.surfaceNrm2 = %playerVector; + + if (vAbs(floorVec(%item.surfaceNrm,100)) $= "0 0 1") + %item.surfaceNrm2 = %playerVector; + else + %item.surfaceNrm2 = vectorNormalize(vectorCross(%item.surfaceNrm,"0 0 -1")); + + %rot = fullRot(%item.surfaceNrm,%item.surfaceNrm2); + + %deplObj = new (%className)() { + dataBlock = SensorLargePulse; + deployed = true; + }; + + // set orientation + %deplObj.setTransform(%item.surfacePt SPC %rot); + + // set team, owner, and handle + %deplObj.team = %plyr.client.Team; + %deplObj.setOwner(%plyr); + + // set power frequency + %deplObj.powerFreq = %plyr.powerFreq; +// setTargetName(%deplObj.target,addTaggedString("Frequency" SPC %deplObj.powerFreq)); + + // set the sensor group if it needs one + if (%deplObj.getTarget() != -1) + setTargetSensorGroup(%deplObj.getTarget(), %plyr.client.team); + + // place the deployable in the MissionCleanup/Deployables group (AI reasons) + addToDeployGroup(%deplObj); + + //let the AI know as well... + AIDeployObject(%plyr.client, %deplObj); + + // play the deploy sound + serverPlay3D(%item.deploySound, %deplObj.getTransform()); + + // increment the team count for this deployed object + $TeamDeployedCount[%plyr.team, %item.item]++; + + addDSurface(%item.surface,%deplObj); + +// %deplObj.playThread($PowerThread,"Power"); + + // take the deployable off the player's back and out of inventory + %plyr.unmountImage(%slot); + %plyr.decInventory(%item.item, 1); + + // Power object + checkPowerObject(%deplObj); + + return %deplObj; +} + +function SensorLargePulse::onDestroyed(%data,%obj,%prevState) { + if (%obj.isRemoved) + return; + if (%obj.deployed) { + %obj.isRemoved = true; + $TeamDeployedCount[%obj.team,LargeSensorDeployable]--; + remDSurface(%obj); + %obj.schedule(500,"delete"); + } + Parent::onDestroyed(%data,%obj,%prevState); +} + +function LargeSensorDeployableImage::onMount(%data, %obj, %node) { + displayPowerFreq(%obj); +} diff --git a/scripts/packs/laserturret.cs b/scripts/packs/laserturret.cs new file mode 100644 index 0000000..8dcf980 --- /dev/null +++ b/scripts/packs/laserturret.cs @@ -0,0 +1,193 @@ +//-------------------------------------------------------------------------- +// Datablocks +//-------------------------------------- + +datablock SensorData(LaserTurretSensor) { + detects = true; + detectsUsingLOS = true; + detectsPassiveJammed = false; + detectsActiveJammed = false; + detectsCloaked = false; + detectionPings = true; + detectRadius = 100; +}; + +datablock TurretData(LaserDeployed) : TurretDamageProfile { + className = DeployedTurret; + shapeFile = "camera.dts"; + mass = 1; + maxDamage = 0.5; + destroyedLevel = 0.5; + disabledLevel = 0.21; + explosion = SmallTurretExplosion; + expDmgRadius = 5.0; + expDamage = 0.25; + expImpulse = 500.0; + repairRate = 0; + heatSignature = 0.0; + deployedObject = true; + thetaMin = 5; + thetaMax = 145; + thetaNull = 90; + primaryAxis = zaxis; + isShielded = true; + energyPerDamagePoint = 30; + maxEnergy = 100; + rechargeRate = 0.15; + barrel = DeployableLaserBarrel; + canControl = true; + cmdCategory = "DTactical"; + cmdIcon = CMDTurretIcon; + cmdMiniIconName = "commander/MiniIcons/com_turret_grey"; + targetNameTag = 'Laser'; + targetTypeTag = 'Turret'; + sensorData = LaserTurretSensor; + sensorRadius = LaserTurretSensor.detectRadius; + sensorColor = "191 0 226"; + firstPersonOnly = true; + renderWhenDestroyed = true; + debrisShapeName = "debris_generic_small.dts"; + debris = TurretDebrisSmall; +}; + +datablock TurretImageData(DeployableLaserBarrel) { + shapeFile = "turret_muzzlepoint.dts"; + item = LaserTurretBarrel; + //rotation = "0 0 0 0"; + offset = "0 0 0"; + projectile = NerfBolt; + //projectileType = TargetProjectile; + projectileType = LinearFlareProjectile; + usesEnergy = true; + fireEnergy = 2; + minEnergy = 8; + lightType = "WeaponFireLight"; + lightColor = "0.25 0.15 0.15 1.0"; + lightTime = "1000"; + lightRadius = "2"; + muzzleFlash = IndoorTurretMuzzleFlash; + //deleteLastProjectile = true; + // Turret parameters + activationMS = 150; + deactivateDelayMS = 300; + thinkTimeMS = 150; + degPerSecTheta = 580; + degPerSecPhi = 960; + attackRadius = 100; + + // State transitions + stateName[0] = "Activate"; + stateTransitionOnNotLoaded[0] = "Dead"; + stateTransitionOnLoaded[0] = "ActivateReady"; + + stateName[1] = "ActivateReady"; + stateSequence[1] = "Activate"; + stateSound[1] = IBLSwitchSound; + stateTimeoutValue[1] = 1; + stateTransitionOnTimeout[1] = "Ready"; + stateTransitionOnNotLoaded[1] = "Deactivate"; + stateTransitionOnNoAmmo[1] = "NoAmmo"; + + stateName[2] = "Ready"; + stateTransitionOnNotLoaded[2] = "Deactivate"; + stateTransitionOnTriggerDown[2] = "Fire"; + stateTransitionOnNoAmmo[2] = "NoAmmo"; + + stateName[3] = "Fire"; + stateTransitionOnTimeout[3] = "Reload"; + stateTimeoutValue[3] = 0.1; + stateFire[3] = true; + stateShockwave[3] = true; + stateRecoil[3] = LightRecoil; + stateAllowImageChange[3] = false; + stateSequence[3] = "Fire"; + stateSound[3] = IBLFireSound; + stateScript[3] = "onFire"; + + stateName[4] ="Reload"; + stateTimeoutValue[4] = 0.05; + stateAllowImageChange[4] = false; + stateSequence[4] = "Reload"; + stateTransitionOnTimeout[4] = "Ready"; + stateTransitionOnNotLoaded[4] = "Deactivate"; + stateTransitionOnNoAmmo[4] = "NoAmmo"; + + stateName[5] = "Deactivate"; + stateSequence[5] = "Activate"; + stateDirection[5] = false; + stateTimeoutValue[5] = 0.1; + stateTransitionOnLoaded[5] = "ActivateReady"; + stateTransitionOnTimeout[5] = "Dead"; + + stateName[6] = "Dead"; + stateTransitionOnLoaded[6] = "ActivateReady"; + + stateName[7] = "NoAmmo"; + stateTransitionOnAmmo[7] = "Reload"; + stateSequence[7] = "NoAmmo"; +}; + +datablock ShapeBaseImageData(TurretLaserDeployableImage) { + mass = 1; + shapeFile = "pack_deploy_turreti.dts"; + item = TurretLaserDeployable; + mountPoint = 1; + offset = "0 0 0"; + deployed = LaserDeployed; + stateName[0] = "Idle"; + stateTransitionOnTriggerDown[0] = "Activate"; + + stateName[1] = "Activate"; + stateScript[1] = "onActivate"; + stateTransitionOnTriggerUp[1] = "Idle"; + + isLarge = true; + emap = true; + maxDepSlope = 360; + deploySound = TurretDeploySound; + minDeployDis = 0.5; + maxDeployDis = 5.0; +}; + +datablock ItemData(TurretLaserDeployable) { + className = Pack; + catagory = "Deployables"; + shapeFile = "pack_deploy_turreti.dts"; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 1; + rotate = false; + image = TurretLaserDeployableImage; + pickUpName = "a laser turret pack"; + emap = true; +}; + +//-------------------------------------------------------------------------- +// Functions +//-------------------------------------- + +function TurretLaserDeployableImage::TestNoTerrainFound(%item) { + // created to prevent console errors +} + +function TurretLaserDeployableImage::TestNoInteriorFound(%item) { + // created to prevent console errors +} + +function TurretLaserDeployable::onPickup(%this, %obj, %shape, %amount) { + //created to prevent console errors +} + +function LaserDeployed::onDestroyed(%this, %obj, %prevState) { + if (%obj.isRemoved) + return; + if ($Host::InvincibleDeployables != 1 || %obj.damageFailedDecon) { + %obj.isRemoved = true; + $TeamDeployedCount[%obj.team, TurretLaserDeployable]--; + remDSurface(%obj); + %obj.schedule(500, delete); + } + Parent::onDestroyed(%this, %obj, %prevState); + +} diff --git a/scripts/packs/lightpack.cs b/scripts/packs/lightpack.cs new file mode 100644 index 0000000..151e7ac --- /dev/null +++ b/scripts/packs/lightpack.cs @@ -0,0 +1,273 @@ +//--------------------------------------------------------- +// Deployable Light +//--------------------------------------------------------- + +%colourOn = 0.5; +%colourOff = 0.1; + +%strobeColourOn = 1.0; +%strobeColourOff = 0.0; + +datablock StaticShapeData(DeployedLightBase) : StaticShapeDamageProfile { + className = "lightbase"; + shapeFile = "pack_deploy_sensor_motion.dts"; + + maxDamage = 0.5; + destroyedLevel = 0.5; + disabledLevel = 0.3; + + maxEnergy = 50; + rechargeRate = 0.25; + + explosion = HandGrenadeExplosion; + expDmgRadius = 1.0; + expDamage = 0.05; + expImpulse = 200; + + dynamicType = $TypeMasks::StaticShapeObjectType; + deployedObject = true; + cmdCategory = "DSupport"; + cmdIcon = CMDSensorIcon; + cmdMiniIconName = "commander/MiniIcons/com_deploymotionsensor"; + targetNameTag = 'Deployed Light'; + deployAmbientThread = true; + debrisShapeName = "debris_generic_small.dts"; + debris = DeployableDebris; + heatSignature = 0; +}; + +datablock ItemData(DeployedLight) { + shapeFile = "turret_muzzlepoint.dts"; + hasLight = true; + lightType = "ConstantLight"; + lightColor = "1.0 1.0 1.0 1.0"; + lightTime = "1000"; + lightRadius = "15"; +}; + +// Constant + +datablock ItemData(DeployedLight0) : DeployedLight { + lightColor = %colourOn SPC %colourOn SPC %colourOn; +}; + +datablock ItemData(DeployedLight1) : DeployedLight { + lightColor = %colourOn SPC %colourOff SPC %colourOff; +}; + +datablock ItemData(DeployedLight2) : DeployedLight { + lightColor = %colourOff SPC %colourOn SPC %colourOff; +}; + +datablock ItemData(DeployedLight3) : DeployedLight { + lightColor = %colourOff SPC %colourOff SPC %colourOn; +}; + +datablock ItemData(DeployedLight4) : DeployedLight { + lightColor = %colourOff SPC %colourOn SPC %colourOn; +}; + +datablock ItemData(DeployedLight5) : DeployedLight { + lightColor = %colourOn SPC %colourOff SPC %colourOn; +}; + +datablock ItemData(DeployedLight6) : DeployedLight { + lightColor = %colourOn SPC %colourOn SPC %colourOff; +}; + +// Strobe + +datablock ItemData(DeployedLight7) : DeployedLight { + lightColor = %strobeColourOn SPC %strobeColourOn SPC %strobeColourOn; + lightType = "PulsingLight"; + lightTime = "50"; + lightRadius = "10"; +}; + +datablock ItemData(DeployedLight8) : DeployedLight { + lightType = "PulsingLight"; + lightColor = %strobeColourOn SPC %strobeColourOff SPC %strobeColourOff; + lightTime = "50"; + lightRadius = "10"; +}; + +datablock ItemData(DeployedLight9) : DeployedLight { + lightType = "PulsingLight"; + lightColor = %strobeColourOff SPC %strobeColourOn SPC %strobeColourOff; + lightTime = "50"; + lightRadius = "10"; +}; + +datablock ItemData(DeployedLight10) : DeployedLight { + lightType = "PulsingLight"; + lightColor = %strobeColourOff SPC %strobeColourOff SPC %strobeColourOn; + lightTime = "50"; + lightRadius = "10"; +}; + +datablock ItemData(DeployedLight11) : DeployedLight { + lightType = "PulsingLight"; + lightColor = %strobeColourOff SPC %strobeColourOn SPC %strobeColourOn; + lightTime = "50"; + lightRadius = "10"; +}; + +datablock ItemData(DeployedLight12) : DeployedLight { + lightType = "PulsingLight"; + lightColor = %strobeColourOn SPC %strobeColourOff SPC %strobeColourOn; + lightTime = "50"; + lightRadius = "10"; +}; + +datablock ItemData(DeployedLight13) : DeployedLight { + lightType = "PulsingLight"; + lightColor = %strobeColourOn SPC %strobeColourOn SPC %strobeColourOff; + lightTime = "50"; + lightRadius = "10"; +}; + +datablock ShapeBaseImageData(LightDeployableImage) { + mass = 1; + emap = true; + shapeFile = "stackable1s.dts"; + item = LightDeployable; + mountPoint = 1; + offset = "0 0 0"; + deployed = DeployedLightBase; + heatSignature = 0; + + stateName[0] = "Idle"; + stateTransitionOnTriggerDown[0] = "Activate"; + + stateName[1] = "Activate"; + stateScript[1] = "onActivate"; + stateTransitionOnTriggerUp[1] = "Idle"; + + isLarge = false; + maxDepSlope = 360; + deploySound = ItemPickupSound; + + minDeployDis = 0.5; + maxDeployDis = 50.0; +}; + +datablock ItemData(LightDeployable) { + className = Pack; + catagory = "Deployables"; + shapeFile = "stackable1s.dts"; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 1; + rotate = true; + image = "LightDeployableImage"; + pickUpName = "a light pack"; + heatSignature = 0; + emap = true; +}; + +function LightDeployableImage::testObjectTooClose(%item) { + return ""; +} + +function LightDeployableImage::testNoTerrainFound(%item) { + // don't check this for non-Landspike turret deployables +} + +function LightDeployable::onPickup(%this, %obj, %shape, %amount) { + // created to prevent console errors +} + +function LightDeployableImage::onDeploy(%item, %plyr, %slot) { + %className = "StaticShape"; + + %playerVector = vectorNormalize(-1 * getWord(%plyr.getEyeVector(),1) SPC getWord(%plyr.getEyeVector(),0) SPC "0"); + + if (vAbs(floorVec(%item.surfaceNrm,100)) $= "0 0 1") + %item.surfaceNrm2 = %playerVector; + else + %item.surfaceNrm2 = vectorNormalize(vectorCross(%item.surfaceNrm,"0 0 -1")); + + %rot = fullRot(%item.surfaceNrm,%item.surfaceNrm2); + + %deplObj = new (%className)() { + dataBlock = %item.deployed; + }; + + %deplObj.light = new Item() { + datablock = DeployedLight @ %plyr.packSet; + static = true; + }; + + // set orientation + %deplObj.setTransform(%item.surfacePt SPC %rot); + adjustLight(%deplObj); + + // set the recharge rate right away + if (%deplObj.getDatablock().rechargeRate) + %deplObj.setRechargeRate(%deplObj.getDatablock().rechargeRate); + + // set team, owner, and handle + %deplObj.team = %plyr.client.Team; + %deplObj.setOwner(%plyr); + %deplObj.light.lightBase = %deplObj; + + // set the sensor group if it needs one + if (%deplObj.getTarget() != -1) + setTargetSensorGroup(%deplObj.getTarget(), %plyr.client.team); + + // place the deployable in the MissionCleanup/Deployables group (AI reasons) + addToDeployGroup(%deplObj); + + //let the AI know as well... + AIDeployObject(%plyr.client, %deplObj); + + // play the deploy sound + serverPlay3D(%item.deploySound, %deplObj.getTransform()); + + // increment the team count for this deployed object + $TeamDeployedCount[%plyr.team, %item.item]++; + + addDSurface(%item.surface,%deplObj); + + %deplObj.playThread($PowerThread,"Power"); + %deplObj.playThread($AmbientThread,"ambient"); + + // take the deployable off the player's back and out of inventory + %plyr.unmountImage(%slot); + %plyr.decInventory(%item.item, 1); + + return %deplObj; +} + +function DeployedLightBase::onDestroyed(%this,%obj,%prevState) { + if (%obj.isRemoved) + return; + %obj.isRemoved = true; + Parent::onDestroyed(%this,%obj,%prevState); + $TeamDeployedCount[%obj.team, LightDeployable]--; + remDSurface(%obj); + %obj.schedule(500, "delete"); + if (isObject(%obj.light)) + %obj.light.schedule(500, "delete"); +} + +function DeployedLightBase::disassemble(%data,%plyr,%obj) { + if (isObject(%obj.light)) + %obj.light.delete(); + disassemble(%data,%plyr,%obj); +} + +function adjustLight(%obj) { + %obj.light.setTransform(vectorAdd(%obj.getPosition(),vectorScale(realVec(%obj,"0 0 1"),1)) SPC %obj.getRotation()); +} + +function LightDeployableImage::onMount(%data, %obj, %node) { + %obj.hasLight = true; // set for lightcheck + %obj.packSet = 0; +} + +function LightDeployableImage::onUnmount(%data, %obj, %node) { + %obj.hasLight = ""; + %obj.packSet = 0; +} diff --git a/scripts/packs/logoprojectorpack.cs b/scripts/packs/logoprojectorpack.cs new file mode 100644 index 0000000..e8cbc06 --- /dev/null +++ b/scripts/packs/logoprojectorpack.cs @@ -0,0 +1,238 @@ +//--------------------------------------------------------- +// Deployable Logo Logo Projector +//--------------------------------------------------------- + +datablock StaticShapeData(DeployedLogoProjector) : StaticShapeDamageProfile { + className = "logoprojector"; + shapeFile = "teamlogo_projector.dts"; + + maxDamage = 0.5; + destroyedLevel = 0.5; + disabledLevel = 0.3; + + isShielded = true; + energyPerDamagePoint = 240; + maxEnergy = 50; + rechargeRate = 0.25; + + explosion = HandGrenadeExplosion; + expDmgRadius = 1.0; + expDamage = 0.05; + expImpulse = 200; + + dynamicType = $TypeMasks::StaticShapeObjectType; + deployedObject = true; + cmdCategory = "DSupport"; + cmdIcon = CMDSensorIcon; + cmdMiniIconName = "commander/MiniIcons/com_deploymotionsensor"; + targetNameTag = 'Deployed Logo Projector'; + deployAmbientThread = true; + debrisShapeName = "debris_generic_small.dts"; + debris = DeployableDebris; + heatSignature = 0; + needsPower = true; +}; + +datablock ShapeBaseImageData(LogoProjectorDeployableImage) { + mass = 1; + emap = true; + shapeFile = "teamlogo_projector.dts"; + item = LogoProjectorDeployable; + mountPoint = 1; + offset = "0 0 0"; + rotation = "-1 0 0 90"; + deployed = DeployedLogoProjector; + heatSignature = 0; + + stateName[0] = "Idle"; + stateTransitionOnTriggerDown[0] = "Activate"; + + stateName[1] = "Activate"; + stateScript[1] = "onActivate"; + stateTransitionOnTriggerUp[1] = "Idle"; + + isLarge = true; + maxDepSlope = 360; + deploySound = ItemPickupSound; + + minDeployDis = 0.1; + maxDeployDis = 50.0; +}; + +datablock ItemData(LogoProjectorDeployable) { + className = Pack; + catagory = "Deployables"; + shapeFile = "stackable1s.dts"; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 1; + rotate = true; + image = "LogoProjectorDeployableImage"; + pickUpName = "a logo projector pack"; + heatSignature = 0; + emap = true; + }; + +function LogoProjectorDeployableImage::testObjectTooClose(%item) { + return ""; +} + +function LogoProjectorDeployableImage::testNoTerrainFound(%item) { + // don't check this for non-Landspike turret deployables +} + +function LogoProjectorDeployable::onPickup(%this, %obj, %shape, %amount) { + // created to prevent console errors +} + +function LogoProjectorDeployableImage::onDeploy(%item, %plyr, %slot) { + %className = "StaticShape"; + + %playerVector = vectorNormalize(-1 * getWord(%plyr.getEyeVector(),1) SPC getWord(%plyr.getEyeVector(),0) SPC "0"); + + if (vAbs(floorVec(%item.surfaceNrm,100)) $= "0 0 1") + %item.surfaceNrm2 = %playerVector; + else + %item.surfaceNrm2 = vectorNormalize(vectorCross(%item.surfaceNrm,"0 0 1")); + + %rot = fullRot(%item.surfaceNrm,%item.surfaceNrm2); + + %deplObj = new (%className)() { + dataBlock = %item.deployed; + }; + + if ($Host::Purebuild == 1) + if (%plyr.packSet == 0) + %logo = 0; + else + %logo = %plyr.packSet; + else { + %logo = 0; + } + + switch (%logo) { + case 1: + %logo = "Base"; + case 2: + %logo = "BaseB"; + case 3: + %logo = "Swolf"; + case 4: + %logo = "DSword"; + case 5: + %logo = "BEagle"; + case 6: + %logo = "COTP"; + case 7: + %logo = "Bioderm"; + default: + %logo = "0"; + } + + if (%logo $= "0") + %deplObj.holoBlock = getTaggedString(Game.getTeamSkin(%plyr.client.team)) @ "Logo"; + else + %deplObj.holoBlock = %logo @ "Logo"; + + %deplObj.holo = new StaticShape() { + datablock = %deplObj.holoBlock; + }; + + // set orientation + %deplObj.setTransform(%item.surfacePt SPC %rot); + adjustHolo(%deplObj); + + // set the recharge rate right away + if (%deplObj.getDatablock().rechargeRate) + %deplObj.setRechargeRate(%deplObj.getDatablock().rechargeRate); + + // set team, owner, and handle + %deplObj.team = %plyr.client.Team; + %deplObj.setOwner(%plyr); + %deplObj.holo.team = %plyr.client.Team; + %deplObj.holo.setOwner(%plyr); + %deplObj.holo.projector = %deplObj; + + // set power frequency + %deplObj.powerFreq = %plyr.powerFreq; + + // place the deployable in the MissionCleanup/Deployables group (AI reasons) + addToDeployGroup(%deplObj); + + //let the AI know as well... + AIDeployObject(%plyr.client,%deplObj); + + // play the deploy sound + serverPlay3D(%item.deploySound, %deplObj.getTransform()); + + // increment the team count for this deployed object + $TeamDeployedCount[%plyr.team, %item.item]++; + + addDSurface(%item.surface,%deplObj); + + // take the deployable off the player's back and out of inventory + %plyr.unmountImage(%slot); + %plyr.decInventory(%item.item, 1); + + // Power object + checkPowerObject(%deplObj); + + return %deplObj; +} + +function DeployedLogoProjector::onDestroyed(%this,%obj,%prevState) { + if (%obj.isRemoved) + return; + %obj.isRemoved = true; + Parent::onDestroyed(%this,%obj,%prevState); + $TeamDeployedCount[%obj.team, LogoProjectorDeployable]--; + remDSurface(%obj); + %obj.schedule(500, "delete"); + if (isObject(%obj.holo)) + %obj.holo.schedule(500, "delete"); + fireBallExplode(%obj,1); +} + +function DeployedLogoProjector::disassemble(%data,%plyr,%obj) { + if (isObject(%obj.holo)) + %obj.holo.delete(); + disassemble(%data,%plyr,%obj); +} + +function DeployedLogoProjector::onGainPowerEnabled(%data,%obj) { + if (shouldChangePowerState(%obj,true)) { + if (isObject(%obj.holo)) + %obj.holo.delete(); + %obj.holo = new StaticShape() { + datablock = %obj.holoBlock; + projector = %obj; + }; + adjustHolo(%obj); + %obj.holo.setScale(%obj.getScale()); + } + Parent::onGainPowerEnabled(%data,%obj); +} + +function DeployedLogoProjector::onLosePowerDisabled(%data,%obj) { + if (shouldChangePowerState(%obj,false)) { + if (isObject(%obj.holo)) + %obj.holo.delete(); + } + Parent::onLosePowerDisabled(%data,%obj); +} + +function adjustHolo(%obj) { + %obj.holo.setTransform(vectorAdd(%obj.getPosition(),vectorScale(realVec(%obj,"0 0 1"),10)) SPC %obj.getRotation()); +} + +function LogoProjectorDeployableImage::onMount(%data, %obj, %node) { + %obj.hasProjector = true; // set for projectorcheck + %obj.packSet = 0; + displayPowerFreq(%obj); +} + +function LogoProjectorDeployableImage::onUnmount(%data, %obj, %node) { + %obj.hasProjector = ""; + %obj.packSet = 0; +} diff --git a/scripts/packs/mediumSensor.cs b/scripts/packs/mediumSensor.cs new file mode 100644 index 0000000..7d98110 --- /dev/null +++ b/scripts/packs/mediumSensor.cs @@ -0,0 +1,127 @@ +//-------------------------------------------------------------------------- +// Medium Pulse Sensor +//-------------------------------------------------------------------------- + +datablock ShapeBaseImageData(MediumSensorDeployableImage) { + mass = 1; + emap = true; + shapeFile = "stackable1s.dts"; + item = MediumSensorDeployable; + mountPoint = 1; + offset = "0 0 0"; + deployed = SensorMediumPulse; + heatSignature = 0; + + stateName[0] = "Idle"; + stateTransitionOnTriggerDown[0] = "Activate"; + + stateName[1] = "Activate"; + stateScript[1] = "onActivate"; + stateTransitionOnTriggerUp[1] = "Idle"; + + isLarge = true; + maxDepSlope = 360; + deploySound = ItemPickupSound; + + minDeployDis = 0.5; + maxDeployDis = 5.0; +}; + +datablock ItemData(MediumSensorDeployable) { + className = Pack; + catagory = "Deployables"; + shapeFile = "stackable1s.dts"; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 1; + rotate = true; + image = "MediumSensorDeployableImage"; + joint = "4.5 4.5 4.5"; + pickUpName = "a medium pulse sensor pack"; + heatSignature = 0; + emap = true; +}; + +function MediumSensorDeployable::onPickup(%this, %obj, %shape, %amount) { + // created to prevent console errors +} + +function MediumSensorDeployableImage::testNoTerrainFound(%item) { + // don't check this for non-Landspike turret deployables +} + +function MediumSensorDeployableImage::onDeploy(%item, %plyr, %slot) { + %className = "StaticShape"; + + %playerVector = vectorNormalize(getWord(%plyr.getEyeVector(),1) SPC -1 * getWord(%plyr.getEyeVector(),0) SPC "0"); + %item.surfaceNrm2 = %playerVector; + + if (vAbs(floorVec(%item.surfaceNrm,100)) $= "0 0 1") + %item.surfaceNrm2 = %playerVector; + else + %item.surfaceNrm2 = vectorNormalize(vectorCross(%item.surfaceNrm,"0 0 -1")); + + %rot = fullRot(%item.surfaceNrm,%item.surfaceNrm2); + + %deplObj = new (%className)() { + dataBlock = SensorMediumPulse; + deployed = true; + }; + + // set orientation + %deplObj.setTransform(%item.surfacePt SPC %rot); + + // set team, owner, and handle + %deplObj.team = %plyr.client.Team; + %deplObj.setOwner(%plyr); + + // set power frequency + %deplObj.powerFreq = %plyr.powerFreq; +// setTargetName(%deplObj.target,addTaggedString("Frequency" SPC %deplObj.powerFreq)); + + // set the sensor group if it needs one + if (%deplObj.getTarget() != -1) + setTargetSensorGroup(%deplObj.getTarget(), %plyr.client.team); + + // place the deployable in the MissionCleanup/Deployables group (AI reasons) + addToDeployGroup(%deplObj); + + //let the AI know as well... + AIDeployObject(%plyr.client, %deplObj); + + // play the deploy sound + serverPlay3D(%item.deploySound, %deplObj.getTransform()); + + // increment the team count for this deployed object + $TeamDeployedCount[%plyr.team, %item.item]++; + + addDSurface(%item.surface,%deplObj); + +// %deplObj.playThread($PowerThread,"Power"); + + // take the deployable off the player's back and out of inventory + %plyr.unmountImage(%slot); + %plyr.decInventory(%item.item, 1); + + // Power object + checkPowerObject(%deplObj); + + return %deplObj; +} + +function SensorMediumPulse::onDestroyed(%data,%obj,%prevState) { + if (%obj.isRemoved) + return; + if (%obj.deployed) { + %obj.isRemoved = true; + $TeamDeployedCount[%obj.team,MediumSensorDeployable]--; + remDSurface(%obj); + %obj.schedule(500,"delete"); + } + Parent::onDestroyed(%data,%obj,%prevState); +} + +function MediumSensorDeployableImage::onMount(%data, %obj, %node) { + displayPowerFreq(%obj); +} diff --git a/scripts/packs/missilerackturret.cs b/scripts/packs/missilerackturret.cs new file mode 100644 index 0000000..531c852 --- /dev/null +++ b/scripts/packs/missilerackturret.cs @@ -0,0 +1,455 @@ +//-------------------------------------------------------------------------- +// Datablocks +//-------------------------------------- + +datablock AudioProfile(MissileRackTurretFireSound) { + filename = ""; + description = AudioDefault3d; + preload = true; + effect = MissileFireEffect; +}; + +datablock AudioProfile(MissileRackTurretFireSound2) { + filename = "fx/weapons/sniper_miss.wav"; + description = AudioDefault3d; + preload = true; +}; + +datablock SensorData(MissileRackTurretSensor) { + detects = true; + detectsUsingLOS = true; + detectsPassiveJammed = false; + detectsActiveJammed = false; + detectsCloaked = false; + detectionPings = true; + detectRadius = 100; +}; + +//--------------------------------------------------------------------------- +// Explosions +//--------------------------------------------------------------------------- +datablock ExplosionData(MissileRackMissileExplosion) { + explosionShape = "effect_plasma_explosion.dts"; + playSpeed = 1.5; + soundProfile = GrenadeExplosionSound; + 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; +}; + +//-------------------------------------------------------------------------- +// Projectile +//-------------------------------------- +datablock SeekerProjectileData(MissileRackMissile) { + casingShapeName = "weapon_missile_casement.dts"; + projectileShapeName = "weapon_missile_projectile.dts"; + hasDamageRadius = true; + indirectDamage = 0.2; + damageRadius = 4.0; + radiusDamageType = $DamageType::MissileTurret; + kickBackStrength = 1000; + + explosion = "MissileRackMissileExplosion"; + splash = MissileSplash; + velInheritFactor = 0.2; // 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 = 6000; + muzzleVelocity = 10.0; + maxVelocity = 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 TurretData(MissileRackTurretDeployed) : TurretDamageProfile { + className = DeployedTurret; + shapeFile = "turret_outdoor_deploy.dts"; + + rechargeRate = 0.15; + + mass = 1; + maxDamage = 0.80; + destroyedLevel = 0.80; + disabledLevel = 0.35; + + explosion = HandGrenadeExplosion; + expDmgRadius = 5.0; + expDamage = 0.5; + expImpulse = 500.0; + + repairRate = 0; + deployedObject = true; + + thetaMin = 0; + thetaMax = 145; + thetaNull = 90; + primaryAxis = zaxis; + + yawVariance = 30.0; // these will smooth out the elf tracking code. + pitchVariance = 30.0; // more or less just tolerances + + isShielded = true; + energyPerDamagePoint = 110; + maxEnergy = 80; + renderWhenDestroyed = true; + barrel = DeployableMissileRackTurretBarrel; + heatSignature = 0.0; + + canControl = true; + cmdCategory = "DTactical"; + cmdIcon = CMDTurretIcon; + cmdMiniIconName = "commander/MiniIcons/com_turret_grey"; + targetNameTag = 'Missile Rack'; + targetTypeTag = 'Turret'; + sensorData = MissileRackTurretSensor; + sensorRadius = MissileRackTurretSensor.detectRadius; + sensorColor = "191 0 226"; + + firstPersonOnly = true; + + debrisShapeName = "debris_generic_small.dts"; + debris = TurretDebrisSmall; + needsPower = true; +}; + +datablock TurretImageData(DeployableMissileRackTurretBarrel) { + shapeFile = "stackable1s.dts"; + rotation = "-0.57735 0.57735 0.57735 120"; + offset = "0 -0.3 0"; + projectile = MissileRackMissile; + projectileType = SeekerProjectile; + + usesEnergy = true; + fireEnergy = 7.0; + minEnergy = 7.0 * 2; + + isSeeker = true; + seekRadius = 300; + maxSeekAngle = 30; + seekTime = 1.0; + minSeekHeat = 0.6; + emap = true; + minTargetingDistance = 15; + + // Turret parameters + activationMS = 250; + deactivateDelayMS = 500; + thinkTimeMS = 200; + degPerSecTheta = 580; + degPerSecPhi = 1080; + attackRadius = 250; + + // State transitions + stateName[0] = "Activate"; + stateTransitionOnNotLoaded[0] = "Dead"; + stateTransitionOnLoaded[0] = "ActivateReady"; + + stateName[1] = "ActivateReady"; + stateSequence[1] = "Activate"; + stateSound[1] = IBLSwitchSound; + + stateTimeoutValue[1] = 1; + stateTransitionOnTimeout[1] = "Ready"; + stateTransitionOnNotLoaded[1] = "Deactivate"; + stateTransitionOnNoAmmo[1] = "NoAmmo"; + + stateName[2] = "Ready"; + stateTransitionOnNotLoaded[2] = "Deactivate"; + stateTransitionOnTriggerDown[2] = "Fire"; + stateTransitionOnNoAmmo[2] = "NoAmmo"; + + stateName[3] = "Fire"; + stateTransitionOnTimeout[3] = "Reload"; + stateTimeoutValue[3] = 0.3; + stateFire[3] = true; + stateShockwave[3] = true; + stateRecoil[3] = LightRecoil; + stateAllowImageChange[3] = false; + stateSequence[3] = "Fire"; + stateSound[3] = MissileRackTurretFireSound; + stateScript[3] = "onFire"; + + stateName[4] ="Reload"; + stateTimeoutValue[4] = 0.5; + stateAllowImageChange[4] = false; + stateSequence[4] = "Reload"; + stateTransitionOnTimeout[4] = "Ready"; + stateTransitionOnNotLoaded[4] = "Deactivate"; + stateTransitionOnNoAmmo[4] = "NoAmmo"; + + stateName[5] = "Deactivate"; + stateSequence[5] = "Activate"; + stateDirection[5] = false; + stateTimeoutValue[5] = 2; + stateTransitionOnLoaded[5] = "ActivateReady"; + stateTransitionOnTimeout[5] = "Dead"; + + stateName[6] = "Dead"; + stateTransitionOnLoaded[6] = "ActivateReady"; + + stateName[7] = "NoAmmo"; + stateTransitionOnAmmo[7] = "Reload"; + stateSequence[7] = "NoAmmo"; + + muzzleSlots = 12; + muzzleSlotOffset[0] = "0.65 0.5 0.4"; + muzzleSlotOffset[1] = "0.35 0.5 0.4"; + muzzleSlotOffset[2] = "0.15 0.5 0.4"; + muzzleSlotOffset[3] = "-0.15 0.5 0.4"; + muzzleSlotOffset[4] = "-0.35 0.5 0.4"; + muzzleSlotOffset[5] = "-0.65 0.5 0.4"; + muzzleSlotOffset[6] = "0.65 0.5 0.1"; + muzzleSlotOffset[7] = "0.35 0.5 0.1"; + muzzleSlotOffset[8] = "0.15 0.5 0.1"; + muzzleSlotOffset[9] = "-0.15 0.5 0.1"; + muzzleSlotOffset[10] = "-0.35 0.5 0.1"; + muzzleSlotOffset[11] = "-0.65 0.5 0.1"; +}; + +datablock TurretImageData(DeployableMissileRackTurretBarrelR) { + shapeFile = "stackable1s.dts"; + rotation = "-0.57735 0.57735 0.57735 120"; + offset = "0 -0.3 0.5"; + +}; + +datablock TurretImageData(DeployableMissileRackTurretBarrelL) { + shapeFile = "stackable1s.dts"; + rotation = "-0.57735 0.57735 0.57735 120"; + offset = "0 -0.3 -0.5"; +}; + +function DeployableMissileRackTurretBarrel::onMount(%this,%obj,%slot) { + %obj.currentMuzzleSlot = 0; + %obj.schedule(1000,"mountImage",DeployableMissileRackTurretBarrelR,1,true); + %obj.schedule(1000,"mountImage",DeployableMissileRackTurretBarrelL,2,true); +} + +// TODO - handle unmount + +datablock ShapeBaseImageData(TurretMissileRackDeployableImage) { + mass = 1; + shapeFile = "pack_deploy_turreto.dts"; + item = TurretMissileRackDeployable; + mountPoint = 1; + offset = "0 0 0"; + deployed = MissileRackTurretDeployed; + stateName[0] = "Idle"; + stateTransitionOnTriggerDown[0] = "Activate"; + + stateName[1] = "Activate"; + stateScript[1] = "onActivate"; + stateTransitionOnTriggerUp[1] = "Idle"; + + isLarge = true; + emap = true; + maxDepSlope = 360; + deploySound = TurretDeploySound; + minDeployDis = 0.5; + maxDeployDis = 5.0; +}; + +datablock ItemData(TurretMissileRackDeployable) { + className = Pack; + catagory = "Deployables"; + shapeFile = "pack_deploy_turreti.dts"; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 1; + rotate = false; + image = TurretMissileRackDeployableImage; + pickUpName = "a missile rack turret pack"; + emap = true; +}; + +//-------------------------------------------------------------------------- +// Functions +//-------------------------------------- + +function TurretMissileRackDeployableImage::TestNoTerrainFound(%item) { + // created to prevent console errors +} + +function TurretMissileRackDeployableImage::TestNoInteriorFound(%item) { + // created to prevent console errors +} + +function TurretMissileRackDeployable::onPickup(%this, %obj, %shape, %amount) { + //created to prevent console errors +} + +function TurretMissileRackDeployableImage::onDeploy(%item, %plyr, %slot) { + %className = "Turret"; + + %playerVector = vectorNormalize(getWord(%plyr.getEyeVector(),1) SPC -1 * getWord(%plyr.getEyeVector(),0) SPC "0"); + + if (vAbs(floorVec(%item.surfaceNrm,100)) $= "0 0 1") + %item.surfaceNrm2 = %playerVector; + else + %item.surfaceNrm2 = vectorNormalize(vectorCross(%item.surfaceNrm,"0 0 1")); + + %rot = fullRot(%item.surfaceNrm,%item.surfaceNrm2); + + %deplObj = new (%className)() { + dataBlock = %item.deployed; + }; + + if (%plyr.packSet == 1) + %deplObj.isSeeker = true; + + // set orientation + %deplObj.setTransform(%item.surfacePt SPC %rot); + + // set team, owner, and handle + %deplObj.team = %plyr.client.Team; + %deplObj.setOwner(%plyr); + + // set power frequency + %deplObj.powerFreq = %plyr.powerFreq; + + // set the sensor group if it needs one + if (%deplObj.getTarget() != -1) + setTargetSensorGroup(%deplObj.getTarget(), %plyr.client.team); + + // place the deployable in the MissionCleanup/Deployables group (AI reasons) + addToDeployGroup(%deplObj); + + //let the AI know as well... + AIDeployObject(%plyr.client, %deplObj); + + // play the deploy sound + serverPlay3D(%item.deploySound, %deplObj.getTransform()); + + // increment the team count for this deployed object + $TeamDeployedCount[%plyr.team, %item.item]++; + + %deplObj.deploy(); + + // Power object + checkPowerObject(%deplObj); + + addDSurface(%item.surface,%deplObj); + + // take the deployable off the player's back and out of inventory + %plyr.unmountImage(%slot); + %plyr.decInventory(%item.item, 1); + + return %deplObj; +} + +function MissileRackTurretDeployed::onDestroyed(%this, %obj, %prevState) { + if (%obj.isRemoved) + return; + if ($Host::InvincibleDeployables != 1 || %obj.damageFailedDecon) { + %obj.isRemoved = true; + $TeamDeployedCount[%obj.team, TurretMissileRackDeployable]--; + remDSurface(%obj); + %obj.schedule(500, delete); + } + Parent::onDestroyed(%this, %obj, %prevState); +} + +function DeployableMissileRackTurretBarrel::onFire(%data,%obj,%slot) { + %targetObj = %obj.getTargetObject(); + if (%targetObj) { + if (!%obj.getDataBlock().hasLOS(%obj,%slot,%targetObj) && %obj.aquireTime + 2000 < getSimTime()) { + %obj.clearTarget(); + return; + } + if (%obj.aquireTime + 10000 + getRandom(0,1000) < getSimTime()) { + %obj.clearTarget(); + return; + } + } + + %p = Parent::onFire(%data,%obj,%slot); + serverPlay3D(MissileRackTurretFireSound2,%obj.getTransform()); + + if (%obj.isSeeker) { + if (%obj.getControllingClient()) + // a player is controlling the turret + %target = %obj.getLockedTarget(); + else + // The ai is controlling the turret + %target = %obj.getTargetObject(); + + if(%target) + %p.setObjectTarget(%target); + else if(%obj.isLocked()) + %p.setPositionTarget(%obj.getLockedPosition()); + else + %p.setNoTarget(); // set as unguided. Only happens when itchy trigger can't wait for lock tone. + %obj.setEnergyLevel(%obj.getEnergyLevel() - (%data.fireEnergy)); + } +} + +function MissileRackTurretDeployed::hasLOS(%data,%obj,%slot,%targetObj) { + %start = %obj.getMuzzlePoint(%slot); + %end = %targetObj.getWorldBoxCenter(); + %res = containerRayCast(%start,%end,-1,%obj); + return firstWord(%res) == %targetObj; +} + +function TurretMissileRackDeployableImage::onMount(%data, %obj, %node) { + %obj.hasMissileRack = true; // set for missilerackcheck + %obj.packSet = 0; + displayPowerFreq(%obj); +} + +function TurretMissileRackDeployableImage::onUnmount(%data, %obj, %node) { + %obj.hasMissileRack = ""; + %obj.packSet = 0; +} diff --git a/scripts/packs/mspine.cs b/scripts/packs/mspine.cs new file mode 100644 index 0000000..0daf151 --- /dev/null +++ b/scripts/packs/mspine.cs @@ -0,0 +1,282 @@ +//--------------------------------------------------------- +// Deployable mspine, Code by Parousia +//--------------------------------------------------------- + +datablock StaticShapeData(DeployedMSpine) : StaticShapeDamageProfile { + className = "mspine"; + shapeFile = "dmiscf.dts"; + + maxDamage = 5.0; + destroyedLevel = 5.0; + disabledLevel = 2.5; + + isShielded = true; + energyPerDamagePoint = 240; + maxEnergy = 50; + rechargeRate = 0.25; + + explosion = HandGrenadeExplosion; + expDmgRadius = 5.0; + expDamage = 0.5; + expImpulse = 200.0; + + dynamicType = $TypeMasks::StaticShapeObjectType; + deployedObject = true; + cmdCategory = "DSupport"; + cmdIcon = CMDSensorIcon; + cmdMiniIconName = "commander/MiniIcons/com_deploymotionsensor"; + targetNameTag = 'Medium Support Beam'; + deployAmbientThread = true; + debrisShapeName = "debris_generic_small.dts"; + debris = DeployableDebris; + heatSignature = 0; + needsPower = true; +}; + +datablock StaticShapeData(DeployedMSpinering) : DeployedMSpine { + maxDamage = 1.0; + destroyedLevel = 1.0; + disabledLevel = 0.75; +}; + +datablock ShapeBaseImageData(mspineDeployableImage) { + mass = 1; + emap = true; + shapeFile = "stackable1s.dts"; + item = mspineDeployable; + mountPoint = 1; + offset = "0 0 0"; + deployed = DeployedMSpine; + heatSignature = 0; + + stateName[0] = "Idle"; + stateTransitionOnTriggerDown[0] = "Activate"; + + stateName[1] = "Activate"; + stateScript[1] = "onActivate"; + stateTransitionOnTriggerUp[1] = "Idle"; + + isLarge = true; + maxDepSlope = 360; + deploySound = ItemPickupSound; + + minDeployDis = 0.1; + maxDeployDis = 50.0; +}; + +datablock ItemData(mspineDeployable) { + className = Pack; + catagory = "Deployables"; + shapeFile = "stackable1s.dts"; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 1; + joint = "1 1 1"; + rotate = true; + image = "mspineDeployableImage"; + pickUpName = "a medium support beam pack"; + heatSignature = 0; + emap = true; +}; + +function mspineDeployableImage::testObjectTooClose(%item) { + return ""; +} + +function mspineDeployableImage::testNoTerrainFound(%item) { + // don't check this for non-Landspike turret deployables +} + +function mspineDeployable::onPickup(%this, %obj, %shape, %amount) { + // created to prevent console errors +} + +function mspineDeployableImage::onDeploy(%item, %plyr, %slot) { + //Object + %className = "StaticShape"; + + %grounded = 0; + if (%item.surface.getClassName() $= TerrainBlock) + %grounded = 1; + + %playerVector = vectorNormalize(-1 * getWord(%plyr.getEyeVector(),1) SPC getWord(%plyr.getEyeVector(),0) SPC "0"); + + if (%item.surfaceinher == 0) { + if (vAbs(floorVec(%item.surfaceNrm,100)) $= "0 0 1") + %item.surfaceNrm2 = %playerVector; + else + %item.surfaceNrm2 = vectorNormalize(vectorCross(%item.surfaceNrm,"0 0 1")); + } + + %rot = fullRot(%item.surfaceNrm,%item.surfaceNrm2); + %scale = getWords($packSetting["mspine",%plyr.packSet],0,2); + + %mod = 0.5; + + if (%plyr.packSet >= 5 && %plyr.packSet < 8) { + %space = rayDist(%item.surfacePt SPC %item.surfaceNrm,%scale,$AllObjMask); + + if (%space != getWord(%scale,1)) + %type = 1; + + %scale = getWord(%scale,0) SPC getWord(%scale,0) SPC %space; + if (%plyr.packSet == 7) + %mod = -0.01; + } + + %scaler = getWords($packSetting["mspine",%plyr.packSet],3,5); + + %deplObj = new (%className)() { //Main Spine + dataBlock = %item.deployed; + scale = vectorMultiply(%scale,1/4 SPC 1/3 SPC 2); + }; + + if (%plyr.packSet != 0 && (%plyr.packSet == 6 || %plyr.packSet == 7 || %plyr.expertSet == 1)) { + %deplObj1 = new (%className)() { //Top add + dataBlock = "DeployedMSpinering"; + scale = vectorMultiply(%scaler,1/4 SPC 1/3 SPC 2); + }; + %deplObj2 = new (%className)() { //Bottom add + dataBlock = "DeployedMSpinering"; + scale = vectorMultiply(%scaler,1/4 SPC 1/3 SPC 2); + }; + + %h1=vectorAdd(%item.surfacePt,vectorScale(vectorNormalize(%item.surfaceNrm),%mod)); + %h2=vectorAdd(%item.surfacePt,vectorScale(vectorNormalize(%item.surfaceNrm),GetWord(%scale,2)-%mod-0.5)); + + %deplObj1.setTransform(%h1 SPC %rot); + %deplObj2.setTransform(%h2 SPC %rot); + addDSurface(%deplObj,%deplObj1); + %deplObj1.grounded = %grounded; + %deplObj1.needsFit = 1; + addDSurface(%deplObj,%deplObj2); + %deplObj2.grounded = %grounded; + %deplObj2.needsFit = 1; + %deplObj1.team = %plyr.client.team; + %deplObj1.setOwner(%plyr); + %deplObj2.team = %plyr.client.team; + %deplObj2.setOwner(%plyr); + if(%deplObj1.getTarget() != -1) + setTargetSensorGroup(%deplObj2.getTarget(), %plyr.client.team); + if(%deplObj2.getTarget() != -1) + setTargetSensorGroup(%deplObj2.getTarget(), %plyr.client.team); + addToDeployGroup(%deplObj1); + addToDeployGroup(%deplObj2); + AIDeployObject(%plyr.client, %deplObj1); + AIDeployObject(%plyr.client, %deplObj2); + %deplObj.right = %deplObj1; + %deplObj.left = %deplObj2; + } + +//////////////////////////Apply settings////////////////////////////// + + // [[Location]]: + + // exact: + %deplObj.setTransform(%item.surfacePt SPC %rot); + + // misc info + addDSurface(%item.surface,%deplObj); + + // [[Settings]]: + + %deplObj.grounded = %grounded; + %deplObj.needsFit = 1; + + // [[Normal Stuff]]: + +// if(%deplObj.getDatablock().rechargeRate) +// %deplObj.setRechargeRate(%deplObj.getDatablock().rechargeRate); + + // set team, owner, and handle + %deplObj.team = %plyr.client.team; + %deplObj.setOwner(%plyr); + + // set power frequency + %deplObj.powerFreq = %plyr.powerFreq; + %deplObj.right.powerFreq = %plyr.powerFreq; + %deplObj.left.powerFreq = %plyr.powerFreq; + + // set the sensor group if it needs one + if (%deplObj.getTarget() != -1) + setTargetSensorGroup(%deplObj.getTarget(), %plyr.client.team); + + // place the deployable in the MissionCleanup/Deployables group (AI reasons) + addToDeployGroup(%deplObj); + + //let the AI know as well... + AIDeployObject(%plyr.client, %deplObj); + + // play the deploy sound + serverPlay3D(%item.deploySound, %deplObj.getTransform()); + + // increment the team count for this deployed object + $TeamDeployedCount[%plyr.team, %item.item]++; + + %deplObj.deploy(); + + // Power object + checkPowerObject(%deplObj); + if (isObject(%deplObj.right)) + checkPowerObject(%deplObj.right); + if (isObject(%deplObj.left)) + checkPowerObject(%deplObj.left); + + if (!%type) + deployEffect(%deplObj,%item.surfacePt,%item.surfaceNrm,"mspine"); + else + deployEffect(%deplObj,%item.surfacePt,%item.surfaceNrm,"mspine1"); + + return %deplObj; +} + +function DeployedMSpine::onDestroyed(%this, %obj, %prevState) { + if (%obj.isRemoved) + return; + %obj.isRemoved = true; + Parent::onDestroyed(%this, %obj, %prevState); + $TeamDeployedCount[%obj.team, mspineDeployable]--; + remDSurface(%obj); + %obj.schedule(500, "delete"); + cascade(%obj); + fireBallExplode(%obj,1); + if (isObject(%obj.right)) + %obj.right.schedule(500,setDamageState,Destroyed); + if (isObject(%obj.left)) + %obj.left.schedule(500,setDamageState,Destroyed); +} + +function DeployedMSpinering::onDestroyed(%this, %obj, %prevState) { + if (%obj.isRemoved) + return; + %obj.isRemoved = true; + Parent::onDestroyed(%this, %obj, %prevState); + remDSurface(%obj); + %obj.schedule(500, "delete"); + cascade(%obj); + fireBallExplode(%obj,1); +} + +function DeployedMSpine::disassemble(%data,%plyr,%hTgt) { + if ($Host::Purebuild == 1) { // Remove console spam + if (isObject(%hTgt.right)) + %hTgt.right.getDataBlock().schedule(500,disassemble,0,%hTgt.right); + if (isObject(%hTgt.left)) + %hTgt.left.getDataBlock().schedule(500,disassemble,0,%hTgt.left); + } + disassemble(%data,%plyr,%hTgt); +} + +function mspineDeployableImage::onMount(%data,%obj,%node) { + %obj.hasMSpine = true; // set for mspinecheck + %obj.packSet = 0; + %obj.expertSet = 0; + displayPowerFreq(%obj); +} + +function mspineDeployableImage::onUnmount(%data,%obj,%node) { + %obj.hasMSpine = ""; + %obj.packSet = 0; + %obj.expertSet = 0; +} diff --git a/scripts/packs/repairpack.cs b/scripts/packs/repairpack.cs new file mode 100644 index 0000000..f015c40 --- /dev/null +++ b/scripts/packs/repairpack.cs @@ -0,0 +1,657 @@ +//-------------------------------------------------------------------------- +// Repair Pack +// can be used by any armor type +// when activated, gives user a "repair gun" that can be used to +// repair a damaged object or player. If there is no target in +// range for the repair gun, the user is repaired. + +//-------------------------------------------------------------------------- +// Sounds & feedback effects + +datablock EffectProfile(RepairPackActivateEffect) +{ + effectname = "packs/packs.repairPackOn"; + minDistance = 2.5; + maxDistance = 2.5; +}; + +datablock EffectProfile(RepairPackFireEffect) +{ + effectname = "packs/repair_use"; + minDistance = 2.5; + maxDistance = 5.0; +}; + +datablock AudioProfile(RepairPackActivateSound) +{ + filename = "fx/packs/packs.repairPackOn.wav"; + description = AudioClosest3d; + preload = true; + effect = RepairPackActivateEffect; +}; + +datablock AudioProfile(RepairPackFireSound) +{ + filename = "fx/packs/repair_use.wav"; + description = CloseLooping3d; + preload = true; + effect = RepairPackFireEffect; +}; + +//-------------------------------------------------------------------------- +// Projectile + +datablock RepairProjectileData(DefaultRepairBeam) +{ + sound = RepairPackFireSound; + +// JTL + beamRange = 250; //10 +// End JTL + beamWidth = 0.15; + numSegments = 20; + texRepeat = 0.20; + blurFreq = 10.0; + blurLifetime = 1.0; + cutoffAngle = 25.0; + + textures[0] = "special/redbump2"; + textures[1] = "special/redflare"; + +}; + + +//------------------------------------------------------------------------- +// shapebase datablocks + +datablock ShapeBaseImageData(RepairPackImage) +{ + shapeFile = "pack_upgrade_repair.dts"; + item = RepairPack; + mountPoint = 1; + offset = "0 0 0"; + emap = true; + + gun = RepairGunImage; + + stateName[0] = "Idle"; + stateTransitionOnTriggerDown[0] = "Activate"; + + stateName[1] = "Activate"; + stateScript[1] = "onActivate"; + stateSequence[1] = "fire"; + stateSound[1] = RepairPackActivateSound; + stateTransitionOnTriggerUp[1] = "Deactivate"; + + stateName[2] = "Deactivate"; + stateScript[2] = "onDeactivate"; + stateTransitionOnTimeout[2] = "Idle"; +}; + +datablock ItemData(RepairPack) +{ + className = Pack; + catagory = "Packs"; + shapeFile = "pack_upgrade_repair.dts"; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 2; + rotate = true; + image = "RepairPackImage"; + pickUpName = "a repair pack"; + + lightOnlyStatic = true; + lightType = "PulsingLight"; + lightColor = "1 0 0 1"; + lightTime = 1200; + lightRadius = 4; + + computeCRC = true; + emap = true; +}; + +//-------------------------------------------------------------------------- +// Repair Gun + +datablock ShapeBaseImageData(RepairGunImage) +{ + shapeFile = "weapon_repair.dts"; + offset = "0 0 0"; + + usesEnergy = true; + minEnergy = 3; + cutOffEnergy = 3.1; + emap = true; + + repairFactorPlayer = 0.002; // <--- attention DaveG! + repairFactorObject = 0.004; // <--- attention DaveG! + + stateName[0] = "Activate"; + stateTransitionOnTimeout[0] = "ActivateReady"; + stateTimeoutValue[0] = 0.25; + + stateName[1] = "ActivateReady"; + stateScript[1] = "onActivateReady"; + stateSpinThread[1] = Stop; + stateTransitionOnAmmo[1] = "Ready"; + stateTransitionOnNoAmmo[1] = "ActivateReady"; + + stateName[2] = "Ready"; + stateSpinThread[2] = Stop; + stateTransitionOnNoAmmo[2] = "Deactivate"; + stateTransitionOnTriggerDown[2] = "Validate"; + + stateName[3] = "Validate"; + stateTransitionOnTimeout[3] = "Validate"; + stateTimeoutValue[3] = 0.2; + stateEnergyDrain[3] = 3; + stateSpinThread[3] = SpinUp; + stateScript[3] = "onValidate"; + stateIgnoreLoadedForReady[3] = true; + stateTransitionOnLoaded[3] = "Repair"; + stateTransitionOnNoAmmo[3] = "Deactivate"; + stateTransitionOnTriggerUp[3] = "Deactivate"; + + stateName[4] = "Repair"; + stateSound[4] = RepairPackFireSound; + stateScript[4] = "onRepair"; + stateSpinThread[4] = FullSpeed; + stateAllowImageChange[4] = false; + stateSequence[4] = "activate"; + stateFire[4] = true; + stateEnergyDrain[4] = 9; + stateTimeoutValue[4] = 0.2; + stateTransitionOnTimeOut[4] = "Repair"; + stateTransitionOnNoAmmo[4] = "Deactivate"; + stateTransitionOnTriggerUp[4] = "Deactivate"; + stateTransitionOnNotLoaded[4] = "Validate"; + + stateName[5] = "Deactivate"; + stateScript[5] = "onDeactivate"; + stateSpinThread[5] = SpinDown; + stateSequence[5] = "activate"; + stateDirection[5] = false; + stateTimeoutValue[5] = 0.2; + stateTransitionOnTimeout[5] = "ActivateReady"; +}; + +function RepairPackImage::onUnmount(%data, %obj, %node) +{ + // dismount the repair gun if the player had it mounted + // need the extra "if" statement to avoid a console error message + if(%obj.getMountedImage($WeaponSlot)) + if(%obj.getMountedImage($WeaponSlot).getName() $= "RepairGunImage") + %obj.unmountImage($WeaponSlot); + // if the player was repairing something when the pack was thrown, stop repairing it + if(%obj.repairing != 0) + stopRepairing(%obj); +} + +function RepairPackImage::onActivate(%data, %obj, %slot) +{ + // don't activate the pack if player is piloting a vehicle + messageClient( %obj.triggeredBy.client, 'CloseHud', "", 'scoreScreen' ); + messageClient( %obj.triggeredBy.client, 'CloseHud', "", 'inventoryScreen' ); + + commandToClient(%obj.triggeredBy.client, 'StationVehicleShowHud'); + + if(%obj.isPilot()) + { + %obj.setImageTrigger(%slot, false); + return; + } + + if(!isObject(%obj.getMountedImage($WeaponSlot)) || %obj.getMountedImage($WeaponSlot).getName() !$= "RepairGunImage") + { + messageClient(%obj.client, 'MsgRepairPackOn', '\c2Repair pack activated.'); + + // make sure player's arm thread is "look" + %obj.setArmThread(look); + + // mount the repair gun + %obj.mountImage(RepairGunImage, $WeaponSlot); + // clientCmdsetRepairReticle found in hud.cs + commandToClient(%obj.client, 'setRepairReticle'); + } +} + +function RepairPackImage::onDeactivate(%data, %obj, %slot) +{ + //called when the player hits the "pack" key again (toggle) + %obj.setImageTrigger(%slot, false); + // if repair gun was mounted, unmount it + if(%obj.getMountedImage($WeaponSlot).getName() $= "RepairGunImage") + %obj.unmountImage($WeaponSlot); +} + +function RepairGunImage::onMount(%this,%obj,%slot) +{ + %obj.setImageAmmo(%slot,true); + if ( !isDemo() ) + commandToClient( %obj.client, 'setRepairPackIconOn' ); +} + +function RepairGunImage::onUnmount(%this,%obj,%slot) +{ + // called when player switches to another weapon + + // stop repairing whatever player was repairing + if(%obj.repairing) + stopRepairing(%obj); + + %obj.setImageTrigger(%slot, false); + // "turn off" the repair pack -- player needs to hit the "pack" key to + // activate the repair gun again + %obj.setImageTrigger($BackpackSlot, false); + if ( !isDemo() ) + commandToClient( %obj.client, 'setRepairPackIconOff' ); +} + +function RepairGunImage::onActivateReady(%this,%obj,%slot) +{ + %obj.errMsgSent = false; + %obj.selfRepairing = false; + %obj.repairing = 0; + %obj.setImageLoaded(%slot, false); +} + +function RepairGunImage::onValidate(%this,%obj,%slot) +{ + // this = repairgunimage datablock + // obj = player wielding the repair gun + // slot = weapon slot + + if(%obj.getEnergyLevel() <= %this.cutOffEnergy) + { + stopRepairing(%obj); + return; + } + %repGun = %obj.getMountedImage(%slot); + // muzVec is the vector coming from the repair gun's "muzzle" + %muzVec = %obj.getMuzzleVector(%slot); + // muzNVec = normalized muzVec + %muzNVec = VectorNormalize(%muzVec); + %repairRange = DefaultRepairBeam.beamRange; + // scale muzNVec to the range the repair beam can reach + %muzScaled = VectorScale(%muzNVec, %repairRange); + // muzPoint = the actual point of the gun's "muzzle" + %muzPoint = %obj.getMuzzlePoint(%slot); + // rangeEnd = muzzle point + length of beam + %rangeEnd = VectorAdd(%muzPoint, %muzScaled); + // search for just about anything that can be damaged as well as interiors + %searchMasks = $TypeMasks::PlayerObjectType | $TypeMasks::VehicleObjectType | + $TypeMasks::StaticShapeObjectType | $TypeMasks::TurretObjectType | $TypeMasks::InteriorObjectType; + // search for objects within the beam's range that fit the masks above + %scanTarg = ContainerRayCast(%muzPoint, %rangeEnd, %searchMasks, %obj); + // screen out interiors + if(%scanTarg && !(%scanTarg.getType() & $TypeMasks::InteriorObjectType)) + { + // a target in range was found + %repTgt = firstWord(%scanTarg); + // is the prospective target damaged? + if(%repTgt.notRepairable) + { + // this is an object that cant be repaired at all + // -- mission specific flag set on the object + if(!%obj.errMsgSent) + { + messageClient(%obj.client, 'MsgRepairPackIrrepairable', '\c2Target is not repairable.', %repTgt); + %obj.errMsgSent = true; + } + // if player was repairing something, stop the repairs -- we're done + if(%obj.repairing) + stopRepairing(%obj); + } + else if(%repTgt.getDamageLevel()) + { + // yes, it's damaged + if(%repTgt != %obj.repairing) + { + if(isObject(%obj.repairing)) + stopRepairing(%obj); + + %obj.repairing = %repTgt; + } + // setting imageLoaded to true sends us to repair state (function onRepair) + %obj.setImageLoaded(%slot, true); + } + else + { + // there is a target in range, but it's not damaged + if(!%obj.errMsgSent) + { + // if the target isn't damaged, send a message to that effect only once + // JTL - repair ourselves if target is not damaged + if(%obj.getDamageLevel()) { + if(%obj.repairing != 0) + if(%obj.repairing != %obj) + stopRepairing(%obj); + if(isObject(%obj.repairing)) + stopRepairing(%obj); + + %obj.repairing = %obj; + // quick, to onRepair! + %obj.setImageLoaded(%slot, true); + return; + } + else { + messageClient(%obj.client, 'MsgRepairPackNotDamaged', '\c2Target is not damaged.', %repTgt); + %obj.errMsgSent = true; + } + } + // if player was repairing something, stop the repairs -- we're done + if(%obj.repairing) + stopRepairing(%obj); + } + } + + //AI hack - too many things influence the aiming, so I'm going to force the repair object for bots only + else if (%obj.client.isAIControlled() && isObject(%obj.client.repairObject)) + { + %repTgt = %obj.client.repairObject; + %repPoint = %repTgt.getAIRepairPoint(); + if (%repPoint $= "0 0 0") + %repPoint = %repTgt.getWorldBoxCenter(); + %repTgtVector = VectorNormalize(VectorSub(%muzPoint, %repPoint)); + %aimVector = VectorNormalize(VectorSub(%muzPoint, %rangeEnd)); + + //if the dot product is very close (ie. we're aiming in the right direction) + if (VectorDot(%repTgtVector, %aimVector) > 0.85) + { + //do an LOS to make sure nothing is in the way... + %scanTarg = ContainerRayCast(%muzPoint, %repPoint, %searchMasks, %obj); + if (firstWord(%scanTarg) == %repTgt) + { + // yes, it's damaged + + if(isObject(%obj.repairing)) + stopRepairing(%obj); + + %obj.repairing = %repTgt; + // setting imageLoaded to true sends us to repair state (function onRepair) + %obj.setImageLoaded(%slot, true); + } + } + } + else if(%obj.getDamageLevel()) + { + // there is no target in range, but the player is damaged + // check to see if we were repairing something before -- if so, stop repairing old target + if(%obj.repairing != 0) + if(%obj.repairing != %obj) + stopRepairing(%obj); + if(isObject(%obj.repairing)) + stopRepairing(%obj); + + %obj.repairing = %obj; + // quick, to onRepair! + %obj.setImageLoaded(%slot, true); + } + else + { + // there is no target in range, and the player isn't damaged + if(!%obj.errMsgSent) + { + // send an error message only once + messageClient(%obj.client, 'MsgRepairPackNoTarget', '\c2No target to repair.'); + %obj.errMsgSent = true; + } + stopRepairing(%obj); + } +} + +function RepairGunImage::onRepair(%this,%obj,%slot) +{ + // this = repairgunimage datablock + // obj = player wielding the repair gun + // slot = weapon slot + + if(%obj.getEnergyLevel() <= %this.cutOffEnergy) + { + stopRepairing(%obj); + return; + } + // reset the flag that indicates an error message has been sent + %obj.errMsgSent = false; + %target = %obj.repairing; + if(!%target) + { + // no target -- whoops! never mind + stopRepairing(%obj); + } + else + { + %target.repairedBy = %obj.client; //keep track of who last repaired this item + if(%obj.repairing == %obj) + { + // player is self-repairing + if(%obj.getDamageLevel()) + { + if(!%obj.selfRepairing) + { + // no need for a projectile, just send a message and up the repair rate + messageClient(%obj.client, 'MsgRepairPackPlayerSelfRepair', '\c2Repairing self.'); + %obj.selfRepairing = true; + startRepairing(%obj, true); + } + } + else + { + messageClient(%obj.client, 'MsgRepairPackSelfDone', '\c2Repairs completed on self.'); + stopRepairing(%obj); + %obj.errMsgSent = true; + } + } + else + { + // make sure we still have a target -- more vector fun!!! + %muzVec = %obj.getMuzzleVector(%slot); + %muzNVec = VectorNormalize(%muzVec); + %repairRange = DefaultRepairBeam.beamRange; + %muzScaled = VectorScale(%muzNVec, %repairRange); + %muzPoint = %obj.getMuzzlePoint(%slot); + %rangeEnd = VectorAdd(%muzPoint, %muzScaled); + + %searchMasks = $TypeMasks::PlayerObjectType | $TypeMasks::VehicleObjectType | + $TypeMasks::StaticShapeObjectType | $TypeMasks::TurretObjectType; + + //AI hack to help "fudge" the repairing stuff... + if (%obj.client.isAIControlled() && isObject(%obj.client.repairObject) && %obj.client.repairObject == %obj.repairing) + { + %repTgt = %obj.client.repairObject; + %repPoint = %repTgt.getAIRepairPoint(); + if (%repPoint $= "0 0 0") + %repPoint = %repTgt.getWorldBoxCenter(); + %repTgtVector = VectorNormalize(VectorSub(%muzPoint, %repPoint)); + %aimVector = VectorNormalize(VectorSub(%muzPoint, %rangeEnd)); + + //if the dot product is very close (ie. we're aiming in the right direction) + if (VectorDot(%repTgtVector, %aimVector) > 0.85) + %scanTarg = ContainerRayCast(%muzPoint, %repPoint, %searchMasks, %obj); + } + else + %scanTarg = ContainerRayCast(%muzPoint, %rangeEnd, %searchMasks, %obj); + + if (%scanTarg) + { + %pos = getWords(%scanTarg, 1, 3); + %obstructMask = $TypeMasks::InteriorObjectType | $TypeMasks::TerrainObjectType; + %obstruction = ContainerRayCast(%muzPoint, %pos, %obstructMask, %obj); + if (%obstruction) + %scanTarg = "0"; + } + + if(%scanTarg) + { + // there's still a target out there + %repTgt = firstWord(%scanTarg); + // is the target damaged? + if(%repTgt.getDamageLevel()) + { + if(%repTgt != %obj.repairing) + { + // the target is not the same as the one we were just repairing + // stop repairing old target, start repairing new target + stopRepairing(%obj); + if(isObject(%obj.repairing)) + stopRepairing(%obj); + + %obj.repairing = %repTgt; + // extract the name of what player is repairing based on what it is + // if it's a player, it's the player's name (duh) + // if it's an object, look for a nametag + // if object has no nametag, just say what it is (e.g. generatorLarge) + if(%repTgt.getClassName() $= Player) + %tgtName = getTaggedString(%repTgt.client.name); + else if(%repTgt.getGameName() !$= "") + %tgtName = %repTgt.getGameName(); + else + %tgtName = %repTgt.getDatablock().getName(); + messageClient(%obj.client, 'MsgRepairPackRepairingObj', '\c2Repairing %1.', %tgtName, %repTgt); + startRepairing(%obj, false); + } + else + { + // it's the same target as last time + // changed to fix "2 players can't repair same object" bug + if(%obj.repairProjectile == 0) + { + if(%repTgt.getClassName() $= Player) + %tgtName = getTaggedString(%repTgt.client.name); + else if(%repTgt.getGameName() !$= "") + %tgtName = %repTgt.getGameName(); + else + %tgtName = %repTgt.getDatablock().getName(); + messageClient(%obj.client, 'MsgRepairPackRepairingObj', '\c2Repairing %1.', %tgtName, %repTgt); + startRepairing(%obj, false); + } + } + } + else + { + %rateOfRepair = %this.repairFactorObject; + if(%repTgt.getClassName() $= Player) + { + %tgtName = getTaggedString(%repTgt.client.name); + %rateOfRepair = %this.repairFactorPlayer; + } + else if(%repTgt.getGameName() !$= "") + %tgtName = %repTgt.getGameName(); + else + %tgtName = %repTgt.getDatablock().getName(); + if(%repTgt != %obj.repairing) + { + // it isn't the same object we were repairing previously + messageClient(%obj.client, 'MsgRepairPackNotDamaged', '\c2%1 is not damaged.', %tgtName); + } + else + { + // same target, but not damaged -- we must be done + messageClient(%obj.client, 'MsgRepairPackDone', '\c2Repairs completed.'); + Game.objectRepaired(%repTgt, %tgtName); + } + %obj.errMsgSent = true; + stopRepairing(%obj); + } + } + else + { + // whoops, we lost our target + messageClient(%obj.client, 'MsgRepairPackLostTarget', '\c2Repair target no longer in range.'); + stopRepairing(%obj); + } + } + } +} + +function RepairGunImage::onDeactivate(%this,%obj,%slot) +{ + stopRepairing(%obj); +} + +function stopRepairing(%player) +{ + // %player = the player who was using the repair pack + + if(%player.selfRepairing) + { + // there is no projectile for self-repairing + %player.setRepairRate(%player.getRepairRate() - %player.repairingRate); + %player.selfRepairing = false; + } + else if(%player.repairing > 0) + { + // player was repairing something else + //if(%player.repairing.beingRepaired > 0) + //{ + // don't decrement this stuff if it's already at 0 -- though it shouldn't be + //%player.repairing.beingRepaired--; + %player.repairing.setRepairRate(%player.repairing.getRepairRate() - %player.repairingRate); + //} + if(%player.repairProjectile > 0) + { + // is there a repair projectile? delete it + %player.repairProjectile.delete(); + %player.repairProjectile = 0; + } + } + %player.repairing = 0; + %player.repairingRate = 0; + %player.setImageTrigger($WeaponSlot, false); + %player.setImageLoaded($WeaponSlot, false); +} + +function startRepairing(%player, %self) +{ + // %player = the player who was using the repair pack + // %self = boolean -- is player repairing him/herself? + + if(%self) + { + // one repair, hold the projectile + %player.setRepairRate(%player.getRepairRate() + RepairGunImage.repairFactorPlayer); + %player.selfRepairing = true; + %player.repairingRate = RepairGunImage.repairFactorPlayer; + } + else + { + //if(%player.repairing.beingRepaired $= "") + // %player.repairing.beingRepaired = 1; + //else + // %player.repairing.beingRepaired++; + + //AI hack... + if (%player.client.isAIControlled() && %player.client.repairObject == %player.repairing) + { + %initialPosition = %player.getMuzzlePoint($WeaponSlot); + %initialDirection = VectorSub(%initialPosition, %player.repairing.getWorldBoxCenter()); + } + else + { + %initialDirection = %player.getMuzzleVector($WeaponSlot); + %initialPosition = %player.getMuzzlePoint($WeaponSlot); + } + if(%player.repairing.getClassName() $= Player) + %repRate = RepairGunImage.repairFactorPlayer; + else + %repRate = RepairGunImage.repairFactorObject; + %player.repairing.setRepairRate(%player.repairing.getRepairRate() + %repRate); + + %player.repairingRate = %repRate; + %player.repairProjectile = new RepairProjectile() { + dataBlock = DefaultRepairBeam; + initialDirection = %initialDirection; + initialPosition = %initialPosition; + sourceObject = %player; + sourceSlot = $WeaponSlot; + targetObject = %player.repairing; + }; + MissionCleanup.add(%player.repairProjectile); + } +} + +function RepairPack::onPickup(%this, %obj, %shape, %amount) +{ + // created to prevent console errors +} diff --git a/scripts/packs/satchelCharge.cs b/scripts/packs/satchelCharge.cs new file mode 100644 index 0000000..7b2ccd0 --- /dev/null +++ b/scripts/packs/satchelCharge.cs @@ -0,0 +1,758 @@ +//-------------------------------------------------------------------------- +// Satchel Charge pack +// can be used by any armor type +// when activated, throws the pack -- when activated again (before +// picking up another pack), detonates with a BIG explosion. + +// Set up defaults for nonexisting vars + +$SatchelChargeMultiplier = 1; + +//-------------------------------------------------------------------------- +// Sounds + +datablock EffectProfile(SatchelChargeActivateEffect) +{ + effectname = "packs/satchel_pack_activate"; + minDistance = 2.5; + maxDistance = 2.5; +}; + +datablock EffectProfile(SatchelChargeExplosionEffect) +{ + effectname = "packs/satchel_pack_detonate"; + minDistance = 2.5; + maxDistance = 5.0; +}; + +datablock EffectProfile(SatchelChargePreExplosionEffect) +{ + effectname = "explosions/explosion.xpl03"; + minDistance = 10.0; + maxDistance = 30.0; +}; + +datablock AudioProfile(SatchelChargeActivateSound) +{ + filename = "fx/packs/satchel_pack_activate.wav"; + description = AudioClose3d; + preload = true; + effect = SatchelChargeActivateEffect; +}; + +datablock AudioProfile(SatchelChargeExplosionSound) +{ + filename = "fx/packs/satchel_pack_detonate.wav"; + description = AudioBIGExplosion3d; + preload = true; + effect = SatchelChargeExplosionEffect; +}; + +datablock AudioProfile(SatchelChargePreExplosionSound) +{ + filename = "fx/explosions/explosion.xpl03.wav"; + description = AudioBIGExplosion3d; + preload = true; + effect = SatchelChargePreExplosionEffect; +}; + +datablock AudioProfile(UnderwaterSatchelChargeExplosionSound) +{ + filename = "fx/weapons/mortar_explode_UW.wav"; + description = AudioBIGExplosion3d; + preload = true; + effect = SatchelChargeExplosionEffect; +}; + +//---------------------------------------------------------------------------- +// Satchel Debris +//---------------------------------------------------------------------------- +datablock ParticleData( SDebrisSmokeParticle ) +{ + 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.4 0.4 0.4 1.0"; + colors[1] = "0.3 0.3 0.3 0.5"; + colors[2] = "0.0 0.0 0.0 0.0"; + sizes[0] = 0.0; + sizes[1] = 2.0; + sizes[2] = 3.0; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; +}; + +datablock ParticleEmitterData( SDebrisSmokeEmitter ) +{ + ejectionPeriodMS = 7; + periodVarianceMS = 1; + + ejectionVelocity = 1.0; // A little oomph at the back end + velocityVariance = 0.2; + + thetaMin = 0.0; + thetaMax = 40.0; + + particles = "SDebrisSmokeParticle"; +}; + + +datablock DebrisData( SatchelDebris ) +{ + emitters[0] = SDebrisSmokeEmitter; + + explodeOnMaxBounce = true; + + elasticity = 0.4; + friction = 0.2; + + lifetime = 0.3; + lifetimeVariance = 0.02; +}; + +//---------------------------------------------------------------------------- +// Bubbles +//---------------------------------------------------------------------------- +datablock ParticleData(SatchelBubbleParticle) +{ + 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(SatchelBubbleEmitter) +{ + ejectionPeriodMS = 10; + periodVarianceMS = 0; + ejectionVelocity = 1.0; + ejectionOffset = 7.0; + velocityVariance = 0.5; + thetaMin = 0; + thetaMax = 80; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + particles = "MortarExplosionBubbleParticle"; +}; + +//-------------------------------------------------------------------------- +// Satchel Explosion Particle effects +//-------------------------------------- +datablock ParticleData(SatchelExplosionSmoke) +{ + dragCoeffiecient = 0.4; + gravityCoefficient = -0.0; // rises slowly + inheritedVelFactor = 0.025; + + lifetimeMS = 2000; + lifetimeVarianceMS = 0; + + textureName = "particleTest"; + + useInvAlpha = true; + spinRandomMin = -200.0; + spinRandomMax = 200.0; + + textureName = "special/Smoke/smoke_001"; + + colors[0] = "1.0 0.7 0.0 1.0"; + colors[1] = "0.2 0.2 0.2 0.5"; + colors[2] = "0.0 0.0 0.0 0.0"; + sizes[0] = 7.0; + sizes[1] = 17.0; + sizes[2] = 2.0; + times[0] = 0.0; + times[1] = 0.4; + times[2] = 1.0; +}; + +datablock ParticleEmitterData(SatchelExplosionSmokeEmitter) +{ + ejectionPeriodMS = 10; + periodVarianceMS = 0; + + ejectionVelocity = 14.25; + velocityVariance = 2.25; + + thetaMin = 0.0; + thetaMax = 180.0; + + lifetimeMS = 200; + + particles = "SatchelExplosionSmoke"; +}; + +datablock ParticleData(UnderwaterSatchelExplosionSmoke) +{ + dragCoeffiecient = 105.0; + gravityCoefficient = -0.0; + inheritedVelFactor = 0.025; + + constantAcceleration = -1.0; + + lifetimeMS = 1500; + lifetimeVarianceMS = 0; + + textureName = "particleTest"; + + useInvAlpha = false; + spinRandomMin = -200.0; + spinRandomMax = 200.0; + + textureName = "special/Smoke/smoke_001"; + + colors[0] = "0.4 0.4 1.0 1.0"; + colors[1] = "0.4 0.4 1.0 0.5"; + colors[2] = "0.0 0.0 0.0 0.0"; + sizes[0] = 7.0; + sizes[1] = 17.0; + sizes[2] = 2.0; + times[0] = 0.0; + times[1] = 0.2; + times[2] = 1.0; +}; + +datablock ParticleEmitterData(UnderwaterSatchelExplosionSmokeEmitter) +{ + ejectionPeriodMS = 10; + periodVarianceMS = 0; + + ejectionVelocity = 14.25; + velocityVariance = 2.25; + + thetaMin = 0.0; + thetaMax = 180.0; + + lifetimeMS = 200; + + particles = "UnderwaterSatchelExplosionSmoke"; +}; + + +datablock ParticleData(SatchelSparks) +{ + dragCoefficient = 1; + gravityCoefficient = 0.0; + inheritedVelFactor = 0.2; + constantAcceleration = 0.0; + lifetimeMS = 500; + lifetimeVarianceMS = 150; + textureName = "special/bigSpark"; + colors[0] = "0.56 0.36 0.26 1.0"; + colors[1] = "0.56 0.36 0.26 1.0"; + colors[2] = "1.0 0.36 0.26 0.0"; + sizes[0] = 0.5; + sizes[1] = 0.5; + sizes[2] = 0.75; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; + +}; + +datablock ParticleEmitterData(SatchelSparksEmitter) +{ + ejectionPeriodMS = 1; + periodVarianceMS = 0; + ejectionVelocity = 40; + velocityVariance = 20.0; + ejectionOffset = 0.0; + thetaMin = 0; + thetaMax = 180; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + orientParticles = true; + lifetimeMS = 200; + particles = "SatchelSparks"; +}; + +datablock ParticleData(UnderwaterSatchelSparks) +{ + dragCoefficient = 1; + gravityCoefficient = 0.0; + inheritedVelFactor = 0.2; + constantAcceleration = 0.0; + lifetimeMS = 500; + lifetimeVarianceMS = 350; + textureName = "special/underwaterSpark"; + colors[0] = "0.6 0.6 1.0 1.0"; + colors[1] = "0.6 0.6 1.0 1.0"; + colors[2] = "0.6 0.6 1.0 0.0"; + sizes[0] = 0.5; + sizes[1] = 0.5; + sizes[2] = 0.75; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; + +}; + +datablock ParticleEmitterData(UnderwaterSatchelSparksEmitter) +{ + ejectionPeriodMS = 2; + periodVarianceMS = 0; + ejectionVelocity = 30; + velocityVariance = 5.0; + ejectionOffset = 0.0; + thetaMin = 0; + thetaMax = 70; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + orientParticles = true; + lifetimeMS = 100; + particles = "UnderwaterSatchelSparks"; +}; + + +//--------------------------------------------------------------------------- +// Explosion +//--------------------------------------------------------------------------- + +datablock ExplosionData(SatchelSubExplosion) +{ + explosionShape = "disc_explosion.dts"; + faceViewer = true; + explosionScale = "0.5 0.5 0.5"; + + debris = SatchelDebris; + debrisThetaMin = 10; + debrisThetaMax = 80; + debrisNum = 8; + debrisVelocity = 60.0; + debrisVelocityVariance = 15.0; + + lifetimeMS = 1000; + delayMS = 0; + + emitter[0] = SatchelExplosionSmokeEmitter; + emitter[1] = SatchelSparksEmitter; + + offset = 0.0; + + playSpeed = 1.5; + + sizes[0] = "1.5 1.5 1.5"; + sizes[1] = "3.0 3.0 3.0"; + times[0] = 0.0; + times[1] = 1.0; +}; + +datablock ExplosionData(SatchelSubExplosion2) +{ + explosionShape = "disc_explosion.dts"; + faceViewer = true; + explosionScale = "0.7 0.7 0.7"; + + debris = SatchelDebris; + debrisThetaMin = 10; + debrisThetaMax = 170; + debrisNum = 8; + debrisVelocity = 60.0; + debrisVelocityVariance = 15.0; + + lifetimeMS = 1000; + delayMS = 50; + + emitter[0] = SatchelExplosionSmokeEmitter; + emitter[1] = SatchelSparksEmitter; + + offset = 9.0; + + playSpeed = 1.5; + + sizes[0] = "1.5 1.5 1.5"; + sizes[1] = "1.5 1.5 1.5"; + times[0] = 0.0; + times[1] = 1.0; +}; + +datablock ExplosionData(SatchelSubExplosion3) +{ + explosionShape = "disc_explosion.dts"; + faceViewer = true; + explosionScale = "1.0 1.0 1.0"; + + debris = SatchelDebris; + debrisThetaMin = 10; + debrisThetaMax = 170; + debrisNum = 8; + debrisVelocity = 60.0; + debrisVelocityVariance = 15.0; + + lifetimeMS = 2000; + delayMS = 100; + + emitter[0] = SatchelExplosionSmokeEmitter; + emitter[1] = SatchelSparksEmitter; + + offset = 9.0; + + playSpeed = 2.5; + + 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(SatchelMainExplosion) +{ + soundProfile = SatchelChargePreExplosionSound; + + subExplosion[0] = SatchelSubExplosion; + subExplosion[1] = SatchelSubExplosion2; + subExplosion[2] = SatchelSubExplosion3; +}; + +//--------------------------------------------------------------------------- +// Underwater Explosion +//--------------------------------------------------------------------------- + +datablock ExplosionData(UnderwaterSatchelSubExplosion) +{ + explosionShape = "disc_explosion.dts"; + faceViewer = true; + explosionScale = "0.5 0.5 0.5"; + + + lifetimeMS = 1000; + delayMS = 0; + + emitter[0] = UnderwaterSatchelExplosionSmokeEmitter; + emitter[1] = UnderwaterSatchelSparksEmitter; + emitter[2] = SatchelBubbleEmitter; + + offset = 0.0; + + playSpeed = 0.75; + + sizes[0] = "1.5 1.5 1.5"; + sizes[1] = "2.5 2.5 2.5"; + sizes[2] = "2.0 2.0 2.0"; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; +}; + +datablock ExplosionData(UnderwaterSatchelSubExplosion2) +{ + explosionShape = "disc_explosion.dts"; + faceViewer = true; + explosionScale = "0.7 0.7 0.7"; + + + lifetimeMS = 1000; + delayMS = 50; + + emitter[0] = UnderwaterSatchelExplosionSmokeEmitter; + emitter[1] = UnderwaterSatchelSparksEmitter; + emitter[2] = SatchelBubbleEmitter; + + offset = 9.0; + + playSpeed = 0.75; + + sizes[0] = "1.5 1.5 1.5"; + sizes[1] = "1.0 1.0 1.0"; + sizes[2] = "0.75 0.75 0.75"; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; +}; + +datablock ExplosionData(UnderwaterSatchelSubExplosion3) +{ + explosionShape = "disc_explosion.dts"; + faceViewer = true; + explosionScale = "1.0 1.0 1.0"; + + + lifetimeMS = 2000; + delayMS = 100; + + emitter[0] = UnderwaterSatchelExplosionSmokeEmitter; + emitter[1] = UnderwaterSatchelSparksEmitter; + emitter[2] = SatchelBubbleEmitter; + + offset = 9.0; + + playSpeed = 1.25; + + sizes[0] = "1.0 1.0 1.0"; + 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(UnderwaterSatchelMainExplosion) +{ + soundProfile = UnderwaterSatchelChargeExplosionSound; + + subExplosion[0] = UnderwaterSatchelSubExplosion; + subExplosion[1] = UnderwaterSatchelSubExplosion2; + subExplosion[2] = UnderwaterSatchelSubExplosion3; +}; + + +//-------------------------------------------------------------------------- +// Projectile + +//------------------------------------------------------------------------- +// shapebase datablocks +datablock ShapeBaseImageData(SatchelChargeImage) +{ + shapeFile = "pack_upgrade_satchel.dts"; + item = SatchelCharge; + mountPoint = 1; + offset = "0 0 0"; + emap = true; +}; + +datablock ItemData(SatchelCharge) +{ + className = Pack; + catagory = "Packs"; + image = SatchelChargeImage; + shapeFile = "pack_upgrade_satchel.dts"; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 2; + rotate = true; + pickUpName = "a satchel charge pack"; + + computeCRC = true; +}; + +datablock ItemData(SatchelChargeThrown) +{ + shapeFile = "pack_upgrade_satchel.dts"; + explosion = SatchelMainExplosion; + underwaterExplosion = UnderwaterSatchelMainExplosion; + mass = 1; + elasticity = 0.1; + friction = 0.9; + rotate = false; + pickupRadius = 0; + noTimeout = true; + armDelay = 3000; + maxDamage = 0.6; + + kickBackStrength = 4000; + + computeCRC = true; +}; + +//-------------------------------------------------------------------------- + +function SatchelCharge::onUse(%this, %obj) +{ + if (!$Host::SatchelChargeEnabled) { + if ($Host::Purebuild == 1) + messageAll('msgClient','\c2%1 just tried to drop a Satchel Charge!',%obj.client.name); + else + messageTeam(%obj.client.team,'msgClient','\c2%1 just tried to drop a Satchel Charge!',%obj.client.name); + %obj.decInventory(SatchelCharge, 1); + return; + } + if ($Host::Purebuild == 1) + messageAll('msgClient','\c2%1 just dropped a Satchel Charge!',%obj.client.name); + else + messageTeam(%obj.client.team,'msgClient','\c2%1 just dropped a Satchel Charge!',%obj.client.name); + %item = new Item() { + dataBlock = SatchelChargeThrown; + rotation = "0 0 1 " @ (getRandom() * 360); + scale = $SatchelChargeMultiplier SPC $SatchelChargeMultiplier SPC $SatchelChargeMultiplier; + }; + MissionCleanup.add(%item); + // take pack out of inventory and unmount image + %obj.decInventory(SatchelCharge, 1); + %obj.throwObject(%item); + //error("throwing satchel charge #" @ %item); + %obj.thrownChargeId = %item; + %item.sourceObject = %obj; + %item.armed = false; + %item.damaged = 0.0; + %item.thwart = false; + // arm itself 3 seconds after being thrown + schedule(%item.getDatablock().armDelay, %item, "initArmSatchelCharge", %item); + messageClient(%obj.client, 'MsgSatchelChargePlaced', "\c2Satchel charge deployed."); +} + +function initArmSatchelCharge(%satchel) +{ + // "deet deet deet" sound + %satchel.playAudio(1, SatchelChargeActivateSound); + // also need to play "antenna extending" animation + %satchel.playThread(0, "deploy"); + %satchel.playThread(1, "activate"); + + // delay the actual arming until after sound is done playing + schedule( 2200, 0, "armSatchelCharge", %satchel ); +} + +function armSatchelCharge(%satchel) +{ + %satchel.armed = true; + commandToClient( %satchel.sourceObject.client, 'setSatchelArmed' ); +} + +function detonateSatchelCharge(%player) +{ + %satchelCharge = %player.thrownChargeId; + // can't detonate the satchel charge if it isn't armed + if(!%satchelCharge.armed) + return; + + //error("Detonating satchel charge #" @ %satchelCharge @ " for player #" @ %player); + + if(%satchelCharge.getDamageState() !$= Destroyed) + { + %satchelCharge.setDamageState(Destroyed); + %satchelCharge.blowup(); + } + + // Clear the player's HUD: + if (isObject(%player.client)) + %player.client.clearBackpackIcon(); +} + +function SatchelChargeThrown::onEnterLiquid(%data, %obj, %coverage, %type) +{ + // lava types + if(%type >=4 && %type <= 6) + { + if(%obj.getDamageState() !$= "Destroyed") + { + %obj.armed = true; + detonateSatchelCharge(%obj.sourceObject); + return; + } + } + + // quickSand + if(%type == 7) + if(isObject(%obj.sourceObject)) + %obj.sourceObject.thrownChargeId = 0; + + Parent::onEnterLiquid(%data, %obj, %coverage, %type); +} + +function SatchelChargeImage::onMount(%data, %obj, %node) +{ + %obj.thrownChargeId = 0; +} + +function SatchelChargeImage::onUnmount(%data, %obj, %node) +{ +} + +function SatchelChargeThrown::onDestroyed(%this, %object, %lastState) +{ + if(%object.kaboom) + return; + else + { + %object.kaboom = true; + + // the "thwart" flag is set if the charge is destroyed with weapons rather + // than detonated. A less damaging explosion, but visually the same scale. + if(%object.thwart) + { + messageClient(%object.sourceObject.client, 'msgSatchelChargeDetonate', "\c2Satchel charge destroyed."); + %dmgRadius = 10 * $SatchelChargeMultiplier; + %dmgMod = 0.3 * $SatchelChargeMultiplier; + %expImpulse = limitSatchelImpulse(1000 * $SatchelChargeMultiplier); + %dmgType = $DamageType::Explosion; + } + else + { + messageClient(%object.sourceObject.client, 'msgSatchelChargeDetonate', "\c2Satchel charge detonated!"); + %dmgRadius = 20 * $SatchelChargeMultiplier; + %dmgMod = 1.0 * $SatchelChargeMultiplier; + %expImpulse = limitSatchelImpulse(2500 * $SatchelChargeMultiplier); + %dmgType = $DamageType::SatchelCharge; + } + + %object.blowingUp = true; + RadiusExplosion(%object, %object.getPosition(), %dmgRadius, %dmgMod, %expImpulse, %object.sourceObject, %dmgType); + + %object.schedule(1000, "delete"); + } + + // ------------------------------------------------------------------- + // z0dd - ZOD, 5/8/02. Addition. Satchel bug fix. Prior to fix, + // clients couldn't pick up packs when satchel was destroyed from dmg. + if(isObject(%object.sourceObject)) + %object.sourceObject.thrownChargeId = 0; +} + +function SatchelChargeThrown::onCollision(%data,%obj,%col) +{ + // Do nothing... +} + +function SatchelChargeThrown::damageObject(%data, %targetObject, %sourceObject, %position, %amount, %damageType) +{ + if (!%object.blowingUp) + { + %targetObject.damaged += %amount; + + if(%targetObject.damaged >= %targetObject.getDataBlock().maxDamage && + %targetObject.getDamageState() !$= Destroyed) + { + %targetObject.thwart = true; + %targetObject.setDamageState(Destroyed); + %targetObject.blowup(); + + // clear the player's HUD: + if (isObject(%targetObject.sourceObject.client)) + %targetObject.sourceObject.client.clearBackPackIcon(); + } + } +} + +function SatchelCharge::onPickup(%this, %obj, %shape, %amount) +{ + // created to prevent console errors +} + +function limitSatchelImpulse(%val) { + if (%val > 50000) + %val = 50000; + return %val; +} diff --git a/scripts/packs/solarpanel.cs b/scripts/packs/solarpanel.cs new file mode 100644 index 0000000..811ba15 --- /dev/null +++ b/scripts/packs/solarpanel.cs @@ -0,0 +1,143 @@ +//-------------------------------------------------------------------------- +// Deployable Solar Panel +//-------------------------------------------------------------------------- + +datablock ShapeBaseImageData(SolarPanelDeployableImage) { + mass = 1; + emap = true; + shapeFile = "stackable1s.dts"; + item = SolarPanelDeployable; + mountPoint = 1; + offset = "0 0 0"; + deployed = SolarPanel; + heatSignature = 0; + + stateName[0] = "Idle"; + stateTransitionOnTriggerDown[0] = "Activate"; + + stateName[1] = "Activate"; + stateScript[1] = "onActivate"; + stateTransitionOnTriggerUp[1] = "Idle"; + + isLarge = true; + maxDepSlope = 360; + deploySound = ItemPickupSound; + + minDeployDis = 1.5; + maxDeployDis = 5; +}; + +datablock ItemData(SolarPanelDeployable) { + className = Pack; + catagory = "Deployables"; + shapeFile = "stackable1s.dts"; + mass = 1; + + hasLight = true; + lightType = "PulsingLight"; + lightColor = "0.1 0.8 0.8 1.0"; + lightTime = "1000"; + lightRadius = "3"; + + elasticity = 0.2; + friction = 0.6; + pickupRadius = 3; + rotate = true; + image = "SolarPanelDeployableImage"; + pickUpName = "a solar panel pack"; + heatSignature = 0; + emap = true; +}; + +function SolarPanelDeployableImage::testNoTerrainFound(%item) { + // don't check this for non-Landspike turret deployables +} + +function SolarPanelDeployable::onPickup(%this, %obj, %shape, %amount) { + // created to prevent console errors +} + +function SolarPanelDeployableImage::onDeploy(%item, %plyr, %slot) { + %className = "StaticShape"; + + %playerVector = vectorNormalize(getWord(%plyr.getEyeVector(),1) SPC -1 * getWord(%plyr.getEyeVector(),0) SPC "0"); + + if (vAbs(floorVec(%item.surfaceNrm,100)) $= "0 0 1") + %item.surfaceNrm2 = %playerVector; + else + %item.surfaceNrm2 = vectorNormalize(vectorCross(%item.surfaceNrm,"0 0 -1")); + + %rot = fullRot(%item.surfaceNrm,%item.surfaceNrm2); + + %deplObj = new (%className)() { + dataBlock = SolarPanel; + deployed = true; + }; + + // set orientation + %deplObj.setTransform(%item.surfacePt SPC %rot); + + // set team, owner, and handle + %deplObj.team = %plyr.client.Team; + %deplObj.setOwner(%plyr); + + // set power frequency + %deplObj.powerFreq = %plyr.powerFreq; + setTargetName(%deplObj.target,addTaggedString("Frequency" SPC %deplObj.powerFreq)); + + // set power + %deplObj.setSelfPowered(); + + // set the sensor group if it needs one + if (%deplObj.getTarget() != -1) + setTargetSensorGroup(%deplObj.getTarget(), %plyr.client.team); + + // place the deployable in the MissionCleanup/Deployables group (AI reasons) + addToDeployGroup(%deplObj); + + //let the AI know as well... + AIDeployObject(%plyr.client, %deplObj); + + // play the deploy sound + serverPlay3D(%item.deploySound, %deplObj.getTransform()); + + // increment the team count for this deployed object + $TeamDeployedCount[%plyr.team, %item.item]++; + + addDSurface(%item.surface,%deplObj); + + %deplObj.playThread($PowerThread,"Power"); + + // take the deployable off the player's back and out of inventory + %plyr.unmountImage(%slot); + %plyr.decInventory(%item.item, 1); + + // add to power list + $PowerList = listAdd($PowerList,%deplObj,-1); + + return %deplObj; +} + +function SolarPanel::onDestroyed(%this,%obj,%prevState) { + if (%obj.isRemoved) + return; + if (%obj.deployed && ($Host::InvincibleDeployables != 1 || %obj.damageFailedDecon)) { + %obj.isRemoved = true; + %loc = findWord($PowerList,%obj); + if (%loc !$= "") + $PowerList = listDel($PowerList,%loc); + $TeamDeployedCount[%obj.team,SolarPanelDeployable]--; + remDSurface(%obj); + %obj.schedule(500,"delete"); + } + Parent::onDestroyed(%data,%obj,%prevState); +} + +function SolarPanelDeployableImage::onMount(%data,%obj,%node) { + %obj.hasGen = true; // set for gencheck + displayPowerFreq(%obj); +} + +function SolarPanelDeployableImage::onUnmount(%data,%obj,%node) { + %obj.hasGen = ""; +} diff --git a/scripts/packs/spine.cs b/scripts/packs/spine.cs new file mode 100644 index 0000000..1651501 --- /dev/null +++ b/scripts/packs/spine.cs @@ -0,0 +1,285 @@ +//--------------------------------------------------------- +// Deployable Spine, Code by Mostlikely, Prettied by JackTL +//--------------------------------------------------------- + +datablock StaticShapeData(DeployedSpine) : StaticShapeDamageProfile { + className = "spine"; + shapeFile = "Pmiscf.dts"; + + maxDamage = 0.5; + destroyedLevel = 0.5; + disabledLevel = 0.3; + + isShielded = true; + energyPerDamagePoint = 240; + maxEnergy = 50; + rechargeRate = 0.25; + + explosion = HandGrenadeExplosion; + expDmgRadius = 3.0; + expDamage = 0.1; + expImpulse = 200.0; + + dynamicType = $TypeMasks::StaticShapeObjectType; + deployedObject = true; + cmdCategory = "DSupport"; + cmdIcon = CMDSensorIcon; + cmdMiniIconName = "commander/MiniIcons/com_deploymotionsensor"; + targetNameTag = 'Light Support Beam'; + deployAmbientThread = true; + debrisShapeName = "debris_generic_small.dts"; + debris = DeployableDebris; + heatSignature = 0; + needsPower = true; +}; +datablock StaticShapeData(DeployedSpine2) : StaticShapeDamageProfile { + className = "spine"; + shapeFile = "Xmiscf.dts"; + + maxDamage = 0.5; + destroyedLevel = 0.5; + disabledLevel = 0.3; + + isShielded = true; + energyPerDamagePoint = 240; + maxEnergy = 50; + rechargeRate = 0.25; + + explosion = HandGrenadeExplosion; + expDmgRadius = 3.0; + expDamage = 0.1; + expImpulse = 200.0; + + dynamicType = $TypeMasks::StaticShapeObjectType; + deployedObject = true; + cmdCategory = "DSupport"; + cmdIcon = CMDSensorIcon; + cmdMiniIconName = "commander/MiniIcons/com_deploymotionsensor"; + targetNameTag = 'Light Support Beam'; + deployAmbientThread = true; + debrisShapeName = "debris_generic_small.dts"; + debris = DeployableDebris; + heatSignature = 0; + needsPower = true; +}; +datablock StaticShapeData(DeployedWoodSpine) : StaticShapeDamageProfile { + className = "spine"; + shapeFile = "stackable5m.dts"; + + maxDamage = 0.5; + destroyedLevel = 0.5; + disabledLevel = 0.3; + + isShielded = true; + energyPerDamagePoint = 240; + maxEnergy = 50; + rechargeRate = 0.25; + + explosion = HandGrenadeExplosion; + expDmgRadius = 3.0; + expDamage = 0.1; + expImpulse = 200.0; + + dynamicType = $TypeMasks::StaticShapeObjectType; + deployedObject = true; + cmdCategory = "DSupport"; + cmdIcon = CMDSensorIcon; + cmdMiniIconName = "commander/MiniIcons/com_deploymotionsensor"; + targetNameTag = 'Light Support Beam'; + deployAmbientThread = true; + debrisShapeName = "debris_generic_small.dts"; + debris = DeployableDebris; + heatSignature = 0; + needsPower = true; +}; + +datablock ShapeBaseImageData(spineDeployableImage) { + mass = 1; + emap = true; + shapeFile = "ammo_plasma.dts"; + item = spineDeployable; + mountPoint = 1; + offset = "0 -0.2 -0.55"; + deployed = DeployedSpine; + heatSignature = 0; + + stateName[0] = "Idle"; + stateTransitionOnTriggerDown[0] = "Activate"; + + stateName[1] = "Activate"; + stateScript[1] = "onActivate"; + stateTransitionOnTriggerUp[1] = "Idle"; + + isLarge = false; + maxDepSlope = 360; + deploySound = ItemPickupSound; + + minDeployDis = 0.1; + maxDeployDis = 50.0; +}; + +datablock ItemData(spineDeployable) { + className = Pack; + catagory = "Deployables"; + shapeFile = "stackable1s.dts"; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 1; + rotate = true; + image = "spineDeployableImage"; + pickUpName = "a light support beam pack"; + heatSignature = 0; + emap = true; +}; + +function spineDeployableImage::testObjectTooClose(%item) { + return ""; +} + +function spineDeployableImage::testNoTerrainFound(%item) { + // don't check this for non-Landspike turret deployables +} + +function spineDeployable::onPickup(%this, %obj, %shape, %amount) { + // created to prevent console errors +} + +function spineDeployableImage::onDeploy(%item, %plyr, %slot) { + //Object + %className = "StaticShape"; + + %grounded = 0; + if (%item.surface.getClassName() $= TerrainBlock) + %grounded = 1; + + %playerVector = vectorNormalize(-1 * getWord(%plyr.getEyeVector(),1) SPC getWord(%plyr.getEyeVector(),0) SPC "0"); + + if (%item.surfaceinher == 0) { + if (vAbs(floorVec(%item.surfaceNrm,100)) $= "0 0 1") + %item.surfaceNrm2 = %playerVector; + else + %item.surfaceNrm2 = vectorNormalize(vectorCross(%item.surfaceNrm,"0 0 1")); + } + + %item.surfaceNrm3 = vectorCross(%item.surfaceNrm,%item.surfaceNrm2); + + %rot = fullRot(%item.surfaceNrm,%item.surfaceNrm2); + %scale = getWords($packSetting["spine",%plyr.packSet],0,2); + %dataBlock = %item.deployed; + + if (%plyr.packSet == 5) { + %space = rayDist(%item.surfacePt SPC %item.surfaceNrm,%scale,$AllObjMask); + if (%space != getWord(%scale,1)) + %type = true; + %scale = getWord(%scale,0) SPC getWord(%scale,0) SPC %space; + } + else if (%plyr.packSet == 6 || %plyr.packSet == 7) { + %mCenter = "0 0 -0.5"; + %pad = pad(%item.surfacePt SPC %item.surfaceNrm SPC %item.surfaceNrm2,%scale,%mCenter); + %scale = getWords(%pad,0,2); + %item.surfacePt = getWords(%pad,3,5); + %rot = getWords(%pad,6,9); + if (%plyr.packSet == 7) { + %scale = vectorMultiply(%scale,1.845 SPC 2 SPC 1.744); // Update dfunctions.cs if changed! + %scaleIsSet = 1; + %item.surfacePt = vectorAdd(%item.surfacePt,vectorScale(%item.surfaceNrm3,0.5)); + %rot = rotAdd(%rot,"1 0 0" SPC $Pi); + %dataBlock = "DeployedWoodSpine"; + } + } + + if (!%scaleIsSet) + %scale = vectorMultiply(%scale,1/4 SPC 1/3 SPC 2); + + %deplObj = new (%className)() { + dataBlock = %dataBlock; + scale = %scale; + }; + +//////////////////////////Apply settings////////////////////////////// + + // [[Location]]: + + // exact: + %deplObj.setTransform(%item.surfacePt SPC %rot); + + // misc info + addDSurface(%item.surface,%deplObj); + + // [[Settings]]: + + %deplObj.grounded = %grounded; + %deplObj.needsFit = 1; + + // [[Normal Stuff]]: + +// if(%deplObj.getDatablock().rechargeRate) +// %deplObj.setRechargeRate(%deplObj.getDatablock().rechargeRate); + + // set team, owner, and handle + %deplObj.team = %plyr.client.team; + %deplObj.setOwner(%plyr); + + // set power frequency + %deplObj.powerFreq = %plyr.powerFreq; + + // set the sensor group if it needs one + if (%deplObj.getTarget() != -1) + setTargetSensorGroup(%deplObj.getTarget(), %plyr.client.team); + + // place the deployable in the MissionCleanup/Deployables group (AI reasons) + addToDeployGroup(%deplObj); + + //let the AI know as well... + AIDeployObject(%plyr.client, %deplObj); + + // play the deploy sound + serverPlay3D(%item.deploySound, %deplObj.getTransform()); + + // increment the team count for this deployed object + $TeamDeployedCount[%plyr.team, %item.item]++; + + %deplObj.deploy(); + + // Power object + checkPowerObject(%deplObj); + + if (%pad) + deployEffect(%deplObj,%item.surfacePt,%item.surfaceNrm,"pad"); + else if (%type) + deployEffect(%deplObj,%item.surfacePt,%item.surfaceNrm,"spine1"); + else + deployEffect(%deplObj,%item.surfacePt,%item.surfaceNrm,"spine"); + + return %deplObj; +} + +///////////////////////////////////// + +function DeployedSpine::onDestroyed(%this, %obj, %prevState) { + if (%obj.isRemoved) + return; + %obj.isRemoved = true; + Parent::onDestroyed(%this, %obj, %prevState); + $TeamDeployedCount[%obj.team, spineDeployable]--; + remDSurface(%obj); + %obj.schedule(500, "delete"); + cascade(%obj); + fireBallExplode(%obj,1); +} + +function DeployedWoodSpine::onDestroyed(%this, %obj, %prevState) { + DeployedSpine::onDestroyed(%this, %obj, %prevState); +} + +function spineDeployableImage::onMount(%data, %obj, %node) { + %obj.hasSpine = true; // set for spinecheck + %obj.packSet = 0; + displayPowerFreq(%obj); +} + +function spineDeployableImage::onUnmount(%data, %obj, %node) { + %obj.hasSpine = ""; + %obj.packSet = 0; +} diff --git a/scripts/packs/switch.cs b/scripts/packs/switch.cs new file mode 100644 index 0000000..283db1c --- /dev/null +++ b/scripts/packs/switch.cs @@ -0,0 +1,273 @@ +//-------------------------------------------------------------------------- +// Deployable Switch +//-------------------------------------------------------------------------- + +datablock StaticShapeData(DeployedSwitch) : StaticShapeDamageProfile { + className = "switch"; + shapeFile = "switch.dts"; + + maxDamage = 1.00; + destroyedLevel = 1.00; + disabledLevel = 0.75; + + isShielded = true; + energyPerDamagePoint = 30; + maxEnergy = 100; + rechargeRate = 0.05; + + explosion = HandGrenadeExplosion; + expDmgRadius = 1.0; + expDamage = 0.3; + expImpulse = 500; + + dynamicType = $TypeMasks::StaticShapeObjectType; + deployedObject = true; + cmdCategory = "DSupport"; + cmdIcon = CMDSensorIcon; + cmdMiniIconName = "commander/MiniIcons/com_switch_grey"; + targetNameTag = 'Deployed'; + targetTypeTag = 'Switch'; +// deployAmbientThread = true; + debrisShapeName = "debris_generic_small.dts"; + debris = DeployableDebris; + heatSignature = 0; + emap = true; +}; + +datablock ShapeBaseImageData(SwitchDeployableImage) { + mass = 1; + emap = true; + shapeFile = "stackable1s.dts"; + item = SwitchDeployable; + mountPoint = 1; + offset = "0 0 0"; + deployed = DeployedSwitch; + heatSignature = 0; + + stateName[0] = "Idle"; + stateTransitionOnTriggerDown[0] = "Activate"; + + stateName[1] = "Activate"; + stateScript[1] = "onActivate"; + stateTransitionOnTriggerUp[1] = "Idle"; + + isLarge = true; + maxDepSlope = 360; + deploySound = ItemPickupSound; + + flatMinDeployDis = 0.25; + flatMaxDeployDis = 5.0; + + minDeployDis = 2; + maxDeployDis = 5; +}; + +datablock ItemData(SwitchDeployable) { + className = Pack; + catagory = "Deployables"; + shapeFile = "stackable1s.dts"; + mass = 1; + + hasLight = true; + lightType = "PulsingLight"; + lightColor = "0.1 0.8 0.8 1.0"; + lightTime = "1000"; + lightRadius = "3"; + + elasticity = 0.2; + friction = 0.6; + pickupRadius = 3; + rotate = true; + image = "SwitchDeployableImage"; + pickUpName = "a switch pack"; + heatSignature = 0; + emap = true; +}; + +datablock AudioProfile(SwitchToggledSound) { + filename = "fx/misc/flipflop_taken.wav"; + description = AudioClosest3d; + preload = true; +}; + +function SwitchDeployableImage::testNoTerrainFound(%item) { + // don't check this for non-Landspike turret deployables +} + +function SwitchDeployable::onPickup(%this, %obj, %shape, %amount) { + // created to prevent console errors +} + +function SwitchDeployableImage::onDeploy(%item, %plyr, %slot) { + %className = "StaticShape"; + + %playerVector = vectorNormalize(getWord(%plyr.getEyeVector(),1) SPC -1 * getWord(%plyr.getEyeVector(),0) SPC "0"); + %item.surfaceNrm2 = %playerVector; + + if (vAbs(floorVec(%item.surfaceNrm,100)) $= "0 0 1") + %item.surfaceNrm2 = %playerVector; + else + %item.surfaceNrm2 = vectorNormalize(vectorCross(%item.surfaceNrm,"0 0 -1")); + + %rot = fullRot(%item.surfaceNrm,%item.surfaceNrm2); + + %deplObj = new (%className)() { + scale = "0.5 0.5 0.5"; + dataBlock = DeployedSwitch; + deployed = true; + }; + + %deplObj.switchRadius = $packSetting["switch",%plyr.packSet]; + + // TODO - handle normal state on deploy + if ($Host::ExpertMode == 1) { + if (%plyr.expertSet == 1) + %deplObj.timed = 1; + else if (%plyr.expertSet == 2) + %deplObj.timed = 2; + } + + // set orientation + %deplObj.setTransform(%item.surfacePt SPC %rot); + + // set team, owner, and handle + %deplObj.team = %plyr.client.Team; + %deplObj.setOwner(%plyr); + + // set power frequency + %deplObj.powerFreq = %plyr.powerFreq; + + // set skin + setTargetSkin(%deplObj.target,Game.getTeamSkin(%plyr.client.team)); + + // set power + %deplObj.setSelfPowered(); + setTargetName(%deplObj.target,addTaggedString("Frequency" SPC %deplObj.powerFreq)); + + // set the sensor group if it needs one + if (%deplObj.getTarget() != -1) + setTargetSensorGroup(%deplObj.getTarget(), %plyr.client.team); + + // place the deployable in the MissionCleanup/Deployables group (AI reasons) + addToDeployGroup(%deplObj); + + //let the AI know as well... + AIDeployObject(%plyr.client, %deplObj); + + // play the deploy sound + serverPlay3D(%item.deploySound, %deplObj.getTransform()); + + // increment the team count for this deployed object + $TeamDeployedCount[%plyr.team, %item.item]++; + + addDSurface(%item.surface,%deplObj); + + %deplObj.playThread($PowerThread,"Power"); + %deplObj.playThread($AmbientThread,"ambient"); + + if (%deplObj.timed == 2) { + %deplObj.stopThread($AmbientThread); + setTargetName(%deplObj.target,addTaggedString("Disabled Frequency" SPC %deplObj.powerFreq)); + %deplObj.isSwitchedOff = true; + } + + // take the deployable off the player's back and out of inventory + %plyr.unmountImage(%slot); + %plyr.decInventory(%item.item, 1); + + return %deplObj; +} + +function DeployedSwitch::onCollision(%data,%obj,%col) { + toggleSwitch(%obj,-1,%col); +} + +function toggleSwitch(%obj,%state,%col,%delayed) { + if (%obj.isRemoved) + return; + // TODO - prevent switching while waiting for timed delay / cancel timed delay if switch is hit? + %switchDelay = 1000; + %switchTimedDelay = 5000; + if (%state $= "") + %state = -1; + if (%col == 0 || %col $= "") + %force = true; + if (!%force) { + if (%col.getClassName() !$= "Player") + return; + if (%col.getState() $= "Dead" || %col.FFZapped == true) + return; + if (%obj.team != %col.team && %obj.team != 0) + return; + if (!(%obj.switchTime < getSimTime())) { + messageClient(%col.client, 'msgClient', '\c2Must wait %1 seconds between switching states.',mCeil((%obj.switchTime - getSimTime())/1000)); + return; + } + } + if ((%obj.isSwitchedOff || (%force == true && %state == true)) && !(%force == true && %state == false)) { + %state = true; + %obj.isSwitchedOff = ""; + } + else { + %state = false; + %obj.isSwitchedOff = true; + } + %switchCount = 0; + %count = getWordCount($PowerList); + // TODO - report number of successes and failures + for(%i=0;%i<%count;%i++) { + %powerObj = getWord($PowerList,%i); + if (vectorDist(%obj.getPosition(),%powerObj.getPosition()) < %obj.switchRadius + && !%powerObj.isRemoved && %obj.powerFreq == %powerObj.powerFreq + && %obj.team == %powerObj.team) { + toggleGenerator(%powerObj,%state); + %switchCount++; + } + } + if (%state == true) { + %obj.play3D(SwitchToggledSound); + %obj.playThread($AmbientThread,"ambient"); + setTargetName(%obj.target,addTaggedString("Frequency" SPC %obj.powerFreq)); + if (!%force) + messageClient(%col.client, 'msgClient', '\c2%1 objects attempted switched on.',%switchCount); + } + else { + %obj.play3D(SwitchToggledSound); + %obj.stopThread($AmbientThread); + setTargetName(%obj.target,addTaggedString("Disabled Frequency" SPC %obj.powerFreq)); + if (!%force) + messageClient(%col.client, 'msgClient', '\c2%1 objects attempted switched off.',%switchCount); + } + %obj.switchTime = getSimTime() + %switchDelay; + cancel(%obj.timedSched); + if (%obj.timed > 0 && !%delayed) { + if (%obj.timed == 1) + %obj.timedSched = schedule(%switchTimedDelay,0,toggleSwitch,%obj,1,0,true); + else if (%obj.timed == 2) + %obj.timedSched = schedule(%switchTimedDelay,0,toggleSwitch,%obj,0,0,true); + %obj.switchTime = getSimTime() + %switchDelay + %switchTimedDelay; + } +} + +function DeployedSwitch::onDestroyed(%this,%obj,%prevState) { + if (%obj.isRemoved) + return; + %obj.isRemoved = true; + Parent::onDestroyed(%this, %obj, %prevState); + $TeamDeployedCount[%obj.team, SwitchDeployable]--; + remDSurface(%obj); + %obj.schedule(500, "delete"); +} + +function SwitchDeployableImage::onMount(%data,%obj,%node) { + %obj.hasSwitch = true; // set for switchcheck + %obj.packSet = 2; + %obj.expertSet = 0; + displayPowerFreq(%obj); +} + +function SwitchDeployableImage::onUnmount(%data,%obj,%node) { + %obj.hasSwitch = ""; + %obj.packSet = 0; + %obj.expertSet = 0; +} diff --git a/scripts/packs/telepadpack.cs b/scripts/packs/telepadpack.cs new file mode 100644 index 0000000..6505f1d --- /dev/null +++ b/scripts/packs/telepadpack.cs @@ -0,0 +1,564 @@ +//--------------------------------------------------------- +// Deployable Telepad +//--------------------------------------------------------- + +datablock ShapeBaseImageData(TelePadDeployableImage) { + mass = 1; + emap = true; + shapeFile = "stackable1s.dts"; + item = TelePadPack; + mountPoint = 1; + offset = "0 0 0"; + deployed = TelePadDeployedBase; + heatSignature = 0; + + stateName[0] = "Idle"; + stateTransitionOnTriggerDown[0] = "Activate"; + + stateName[1] = "Activate"; + stateScript[1] = "onActivate"; + stateTransitionOnTriggerUp[1] = "Idle"; + + isLarge = true; + maxDepSlope = 360; + deploySound = StationDeploySound; + + minDeployDis = 0.5; + maxDeployDis = 5.0; +}; + +datablock ItemData(TelePadPack) { + className = Pack; + catagory = "Deployables"; + shapeFile = "stackable1s.dts"; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 1; + rotate = false; + image = "TelePadDeployableImage"; + pickUpName = "a teleport pad pack"; + heatSignature = 0; + joint = "2 2 2"; + computeCRC = true; + emap = true; +}; + +datablock SensorData(TelePadBaseSensorObj) { + detects = true; + detectsUsingLOS = true; + detectsPassiveJammed = false; + detectsActiveJammed = false; + detectsCloaked = false; + detectionPings = true; + detectRadius = 10; +}; + +datablock StaticShapeData(TelePadDeployedBase) : StaticShapeDamageProfile { + className = "teleport"; + shapeFile = "nexuscap.dts"; + + maxDamage = 2.00; + destroyedLevel = 2.00; + disabledLevel = 1.35; + + isShielded = true; + energyPerDamagePoint = 250; + maxEnergy = 100; + rechargeRate = 1; + + explosion = ShapeExplosion; // DeployablesExplosion; + expDmgRadius = 18.0; + expDamage = 0.1; + expImpulse = 200.0; + + dynamicType = $TypeMasks::StationObjectType; + deployedObject = true; + cmdCategory = "DSupport"; + cmdIcon = CMDSwitchIcon; + cmdMiniIconName = "commander/MiniIcons/com_switch_grey"; + targetNameTag = 'Deployed'; + targetTypeTag = 'Teleport Pad'; + + debrisShapeName = "debris_generic.dts"; + debris = DeployableDebris; + + heatSignature = 0; + needsPower = true; + + humSound = SensorHumSound; + pausePowerThread = true; + sensorData = TelePadBaseSensorObj; + sensorRadius = TelePadBaseSensorObj.detectRadius; + sensorColor = "0 212 45"; + firstPersonOnly = true; + + lightType = "PulsingLight"; + lightColor = "0 1 0 1"; + lightTime = 1200; + lightRadius = 6; +}; + +datablock StaticShapeData(TelePadBeam) { + className = "Station"; + catagory = "DSupport"; + shapefile = "nexus_effect.dts"; + collideable = 1; + needsNoPower = true; + emap="true"; + sensorData = TelePadBaseSensorObj; + sensorRadius = TelePadBaseSensorObj.detectRadius; + sensorColor = "0 212 45"; + + cmdCategory = "DSupport"; + targetNameTag = 'Teleport'; + targetTypeTag = 'Pad'; + + lightType = "PulsingLight"; + lightColor = "0 1 0 1"; + lightTime = 1200; + lightRadius = 6; +}; + +datablock AudioProfile(TelePadAccessDeniedSound) { + filename = "gui/vote_nopass.wav"; + description = AudioClosest3d; + preload = true; +}; + +datablock AudioProfile(TelePadBeamSound) { + filename = "fx/vehicles/inventory_pad_on.wav"; + description = AudioClosest3d; + preload = true; +}; + +datablock AudioProfile(TelePadPowerUpSound) { + filename = "fx/powered/turret_heavy_activate.wav"; + description = AudioClosest3d; + preload = true; +}; + +datablock AudioProfile(TelePadPowerDownSound) { + filename = "fx/powered/inv_pad_off.wav"; + description = AudioClosest3d; + preload = true; +}; + +datablock ParticleData(TelePadTeleportParticle) +{ + dragCoeffiecient = 0.0; + gravityCoefficient = 0.0; + inheritedVelFactor = 0.0; + + lifetimeMS = 1200; + lifetimeVarianceMS = 400; + + textureName = "special/lightFalloffMono"; + + useInvAlpha = false; + spinRandomMin = -200.0; + spinRandomMax = 200.0; + + colors[0] = "0.5 0.8 0.2 1.0"; + colors[1] = "0.6 0.9 0.3 1.0"; + colors[2] = "0.7 1.0 0.4 1.0"; + sizes[0] = 0.2; + sizes[1] = 0.1; + sizes[2] = 0.05; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; +}; + +datablock ParticleEmitterData(TelePadTeleportEmitter) +{ + ejectionPeriodMS = 1; + ejectionOffset = 7.0; + periodVarianceMS = 0.0; + ejectionVelocity = 2.0; + velocityVariance = 2.0; + thetaMin = 0.0; + thetaMax = 10.0; + lifetimeMS = 0; + + particles = "TelePadTeleportParticle"; +}; + +function TelePadDeployedBase::onDestroyed(%this,%obj,%prevState) { + if (%obj.isRemoved) + return; + %obj.isRemoved = true; + Parent::onDestroyed(%this,%obj,%prevState); + $TeamDeployedCount[%obj.team,TelePadPack]--; + %obj.isRemoved = true; + remDSurface(%obj); + %obj.beam.schedule(150,"delete"); + %obj.schedule(500,"delete"); +} + +function TelePadDeployedBase::disassemble(%data,%plyr,%obj) { + if (isObject(%obj.beam)) + %obj.beam.delete(); + %obj.isRemoved = true; + disassemble(%data,%plyr,%obj); +} + +function TelePadDeployedBase::onGainPowerEnabled(%data,%obj) { + if (shouldChangePowerState(%obj,true)) { + tp_fadeIn(%obj,true); + %obj.playThread($AmbientThread,"ambient"); + %obj.setThreadDir($AmbientThread,true); + + %obj.playThread($ActivateThread,"transition"); + %obj.setThreadDir($ActivateThread,false); + + %obj.play3D(TelePadPowerUpSound); + } + Parent::onGainPowerEnabled(%data,%obj); +} + +function TelePadDeployedBase::onLosePowerDisabled(%data,%obj) { + if (shouldChangePowerState(%obj,false)) { + tp_fadeOut(%obj,true); + %obj.stopThread($AmbientThread); + + %obj.playThread($ActivateThread,"transition"); + %obj.setThreadDir($ActivateThread,true); + + %obj.play3D(TelePadPowerDownSound); + } + Parent::onLosePowerDisabled(%data,%obj); +} + +function TelePadDeployedBase::onCollision(%data,%obj,%col) { + if (%col.justTeleported || %obj.isRemoved) + return; + + // verify pad.team is team associated and is on player's team + if (%obj.team != %col.team && %obj.team != 0 && %obj.teleMode != 1 && %obj.frequency > 0) { + %obj.play3D(TelePadAccessDeniedSound); + messageClient(%col.client,'msgClient','\c2Access Denied -- Wrong team.'); + %col.justTeleported = true; + schedule(2000,0,"unTeleport",%col); + return; + } + + // verify that pad can transmit + if (%obj.teleMode == 3) { + %obj.play3D(TelePadAccessDeniedSound); + messageClient(%col.client,'msgClient','\c2Access Denied -- This pad can only receive.'); + %col.justTeleported = true; + schedule(2000,0,"unTeleport",%col); + return; + } + + // Discover next pad to teleport to + %dgroup = nameToID(Deployables); + %destPad = 0; + %firstPad = 0; + for(%depIndex = 0; %depIndex < %dgroup.getCount(); %depIndex++) { + %dep = %dgroup.getObject(%depIndex); + if (%dep.getDataBlock().className $= "teleport") { + if (%dep != %obj && %dep.frequency == %obj.frequency && %dep.team == %obj.team && %dep.teleMode != 2) { + if (%dep.isPowered() && %dep.isEnabled() && !(%dep.getEnergyLevel() < %dep.getDataBlock().maxEnergy)) { + if (!%firstPad || %dep < %firstPad) + %firstPad = %dep; + if (%dep > %obj && (!%destPad || %dep < %destPad)) { + %destPad = %dep; + } + } + else + %notEnabled = true; + } + } + } + if (!%destPad) + %destPad = %firstPad; + + if (!%obj.isPowered() || !%obj.isEnabled()) { + %obj.play3D(TelePadAccessDeniedSound); + if (!%obj.isPowered() && !%obj.isEnabled()) + messageClient(%col.client,'msgClient','\c2Unable to teleport, telepad is damaged and has no power.'); + else if (!%obj.isEnabled()) + messageClient(%col.client,'msgClient','\c2Unable to teleport, telepad is damaged.'); + else if (!%obj.isPowered()) + messageClient(%col.client,'msgClient','\c2Unable to teleport, telepad is not powered.'); + else + messageClient(%col.client,'msgClient','\c2Unable to teleport, telepad malfunction.'); + %col.justTeleported = true; + schedule(2000,0,"unTeleport",%col); + return; + } + + if (!%destPad) { + %obj.play3D(TelePadAccessDeniedSound); + if (%notEnabled) + messageClient(%col.client,'msgClient','\c2Unable to teleport, destination is damaged, has no power or is recharging.'); + else + messageClient(%col.client,'msgClient','\c2Unable to teleport, no other pads to teleport to.'); + %col.justTeleported = true; + schedule(2000,0,"unTeleport",%col); + return; + } + + if (tp_isBlocked(%destPad,%col)) { + %obj.play3D(TelePadAccessDeniedSound); + messageClient(%col.client,'msgClient','\c2Unable to teleport, destination is blocked.'); + %col.justTeleported = true; + schedule(2000,0,"unTeleport",%col); + return; + } + + if (%obj.getEnergyLevel() < %obj.getDataBlock().maxEnergy) { + %obj.play3D(TelePadAccessDeniedSound); + messageClient(%col.client,'msgClient','\c2Unable to teleport, telepad is recharging.'); + %col.justTeleported = true; + schedule(2000,0,"unTeleport",%col); + return; + } + + // center player on pad + if (!tp_isBlocked(%obj,%col)) + tp_adjustPlayer(%obj,%col); + + // fade out player + %col.disableMove(true); + pl_fadeOut(%col); + + // pad power up effect + tp_fadePadIn(%obj); + tp_fadePadIn(%destPad); + + // fade out beams + schedule(600,0,"tp_fadeOut",%obj); + schedule(750,0,"tp_fadeOut",%destPad); + + // pad power down effect + schedule(1500,0,"tp_fadePadOut",%obj); + schedule(1550,0,"tp_fadePadOut",%destPad); + + // fade in beams + schedule(3000,0,"tp_fadeIn",%obj); + schedule(3050,0,"tp_fadeIn",%destPad); + + // Zap energy + %obj.setEnergyLevel(0); + %destPad.setEnergyLevel(0); + + %col.justTeleported = true; + + messageClient(%col.client,'msgClient',"~wfx/misc/diagnostic_on.wav"); + schedule(500,0,"teleport",%col,%destPad,%obj); // schedule their teleportation + tp_emitter(%obj); +} + +function tp_isBlocked(%pad,%obj) { + %padPos = %pad.getPosition(); + %telePos = vectorAdd(%padPos,vectorScale(realVec(%pad,"0 0 1"),-2.5)); + if (containerRayCast(%padPos,%telePos,-1,%pad)) + %blocked = true; + if (!$Host::AllowUnderground) { + %terrain = getTerrainHeight2(%telePos); + if (getWord(%telePos,2) < getWord(%terrain,2) || %terrain $= "") + %blocked = true; + } + if (isObject(%obj)) { + %adjust = vectorAdd(vectorScale(vectorNormalize(realVec(%pad,"0 0 1")),-1.35),vectorSub(%obj.getPosition(),%obj.getWorldBoxCenter())); + %pos = vectorAdd(%padPos,%adjust); + if (!$Host::AllowUnderground) { + %terrain = getTerrainHeight2(%pos); + if (getWord(%pos,2) < getWord(%terrain,2) || %terrain $= "") + %blocked = true; + } + if (containerRayCast(%telePos,%pos,-1,%obj)) + %blocked = true; + } + return %blocked; +} + +// player +function pl_fadeIn(%obj) { + %obj.startFade(500,0,false); + messageClient(%col.client,'msgClient',"~wfx/misc/diagnostic_on.wav"); +} + +function pl_fadeOut(%obj) { + %obj.startFade(500,0,true); + messageClient(%col.client,'msgClient',"~wfx/misc/diagnostic_on.wav"); +} + +// beam and sound +function tp_fadeIn(%obj,%silent) { + if (%obj.isPowered() && %obj.isEnabled()) { + if (!%silent) + %obj.play3D(DiscReloadSound); + %obj.beam.startFade(100,0,false); + } +} + +function tp_fadeOut(%obj,%silent) { + if (!%silent) + %obj.play3D(TelePadBeamSound); + %obj.beam.startFade(100,0,true); +} + +// pad +function tp_fadePadIn(%obj) { + %obj.playThread($ActivateThread,"transition"); + %obj.setThreadDir($ActivateThread,true); +} + +function tp_fadePadOut(%obj) { + %obj.playThread($ActivateThread,"transition"); + %obj.setThreadDir($ActivateThread,false); +} + +// fancy emitter +function tp_emitter(%obj) { + %em = new ParticleEmissionDummy() { + scale = "1 1 1"; + dataBlock = "defaultEmissionDummy"; + emitter = "TelePadTeleportEmitter"; + velocity = "1"; + }; + %adjust = vectorScale(realVec(%obj,"0 0 1"),7); + %em.setTransform(vectorAdd(%obj.getPosition(),%adjust) SPC rotAdd(%obj.getRotation(),"1 0 0" SPC $Pi)); + MissionCleanup.add(%em); + %em.schedule(1000,"delete"); +} + +function unTeleport(%pl) { + if (isObject(%pl)) + %pl.justTeleported = false; +} + +function teleport(%pl,%destPad,%src) { + %pl.setVelocity("0 0 0"); //slow me down, ive been falling :) + %pl.schedule(500,disableMove,false); + pl_fadeIn(%pl); + schedule(2650,0,"unTeleport",%pl); + + if (!isObject(%destPad)) {// lost the destination + messageClient(%pl.client,'msgClient','\c2Lost destination!'); + tp_adjustPlayer(%src,%pl); + } + else { + if (%pl.team == %src.team) + messageClient(%pl.client,'msgClient','\c2Teleporting on frequency %1.',%src.frequency); + else + messageClient(%pl.client,'msgClient','\c2Teleporting on ENEMY frequency %1!',%src.frequency); + tp_adjustPlayer(%destPad,%pl); + tp_emitter(%destPad); + } +} + +function tp_adjustPlayer(%pad,%obj) { + %adjust = vectorAdd(vectorScale(vectorNormalize(realVec(%pad,"0 0 1")),-1.35),vectorSub(%obj.getPosition(),%obj.getWorldBoxCenter())); + %rot = %obj.getRotation(); + %obj.setTransform(vectorAdd(%pad.getPosition(),%adjust) SPC %rot); +} + +function tp_adjustBeam(%pad) { + %rot = rotAdd(%pad.getRotation(),"1 0 0" SPC $Pi); + %pad.beam.setTransform(%pad.getPosition() SPC %rot); +} + +function TelePadPack::onPickup(%this,%obj,%shape,%amount) { + // created to prevent console errors +} + +function TelePadDeployableImage::onDeploy(%item,%plyr,%slot) { + %className = "StaticShape"; + + %item.surfacePt = vectorAdd(%item.surfacePt,vectorScale(%item.surfaceNrm,0.4)); + + %playerVector = vectorNormalize(getWord(%plyr.getEyeVector(),1) SPC -1 * getWord(%plyr.getEyeVector(),0) SPC "0"); + %item.surfaceNrm2 = %playerVector; + + if (vAbs(floorVec(%item.surfaceNrm,100)) $= "0 0 1") + %item.surfaceNrm2 = vectorScale(%playerVector,-1); + else + %item.surfaceNrm2 = vectorNormalize(vectorCross(%item.surfaceNrm,"0 0 1")); + + %rot = fullRot(vectorScale(%item.surfaceNrm,-1),%item.surfaceNrm2); + + %deplObj = new (%className)() { + dataBlock = TelePadDeployedBase; + scale = "1 1 1"; + deployed = true; + teleMode = %plyr.expertSet; + }; + + // set orientation + %deplObj.setTransform(%item.surfacePt SPC %rot); + + // set team, owner, and handle + %deplObj.team = %plyr.client.team; + %deplObj.setOwner(%plyr); + + // set power frequency + %deplObj.powerFreq = %plyr.powerFreq; + + // set the sensor group if it needs one + if (%deplObj.getTarget() != -1) + setTargetSensorGroup(%deplObj.getTarget(),%plyr.client.team); + + // set frequency + %frequency = %plyr.packSet; + if (!%frequency) + %frequency = 1; + %deplObj.frequency = %frequency; + setTargetName(%deplObj.target,addTaggedString("Frequency" SPC %frequency)); + + // attach beam + %deplObj.beam = new (StaticShape)() { + dataBlock = TelePadBeam; + scale = "1 1 0.4"; + }; + + // set orientation + tp_adjustBeam(%deplObj); + + %deplObj.beam.playThread(0,"ambient"); + %deplObj.beam.setThreadDir(0,true); + // The flash animation plays forwards, then back automatically,so we have to alternate the thread direcction... + %deplObj.beam.flashThreadDir = true; + + %deplObj.beam.base = %deplObj; + + // place the deployable in the MissionCleanup/Deployables group (AI reasons) + addToDeployGroup(%deplObj); + + //let the AI know as well... + AIDeployObject(%plyr.client,%deplObj); + + // play the deploy sound + serverPlay3D(%item.deploySound,%deplObj.getTransform()); + + // increment the team count for this deployed object + $TeamDeployedCount[%plyr.team,%item.item]++; + + addDSurface(%item.surface,%deplObj); + + // take the deployable off the player's back and out of inventory + %plyr.unmountImage(%slot); + %plyr.decInventory(%item.item,1); + + // Power object + checkPowerObject(%deplObj); + + return %deplObj; +} + +function TelePadDeployableImage::onMount(%data,%obj,%node) { + %obj.hasTele = true; // set for telecheck + %obj.packSet = 1; + %obj.expertSet = 0; + displayPowerFreq(%obj); +} + +function TelePadDeployableImage::onUnmount(%data,%obj,%node) { + %obj.hasTele = ""; + %obj.packSet = 0; + %obj.expertSet = 0; +} diff --git a/scripts/packs/treepack.cs b/scripts/packs/treepack.cs new file mode 100644 index 0000000..993e726 --- /dev/null +++ b/scripts/packs/treepack.cs @@ -0,0 +1,258 @@ +//--------------------------------------------------------- +// Deployable Tree, original code by Parousia +//--------------------------------------------------------- + +datablock StaticShapeData(DeployedTree) : StaticShapeDamageProfile { + className = "tree"; + shapeFile = "borg19.dts"; + + maxDamage = 0.5; + destroyedLevel = 0.5; + disabledLevel = 0.3; + + explosion = HandGrenadeExplosion; + expDmgRadius = 1.0; + expDamage = 0.05; + expImpulse = 200; + + dynamicType = $TypeMasks::StaticShapeObjectType; + deployedObject = true; + cmdCategory = "DSupport"; + cmdIcon = CMDSensorIcon; + cmdMiniIconName = "commander/MiniIcons/com_deploymotionsensor"; + targetNameTag = 'Deployed Tree'; + deployAmbientThread = true; + debrisShapeName = "debris_generic_small.dts"; + debris = DeployableDebris; + heatSignature = 0; +}; + +datablock StaticShapeData(DeployedTree0) : DeployedTree { + shapeFile = "borg16.dts"; +}; + +datablock StaticShapeData(DeployedTree1) : DeployedTree { + shapeFile = "borg17.dts"; +}; + +datablock StaticShapeData(DeployedTree2) : DeployedTree { + shapeFile = "borg18.dts"; +}; + +datablock StaticShapeData(DeployedTree3) : DeployedTree { + shapeFile = "borg19.dts"; +}; + +datablock StaticShapeData(DeployedTree4) : DeployedTree { + shapeFile = "dorg15.dts"; +}; + +datablock StaticShapeData(DeployedTree5) : DeployedTree { + shapeFile = "dorg16.dts"; +}; + +datablock StaticShapeData(DeployedTree6) : DeployedTree { + shapeFile = "dorg17.dts"; +}; + +datablock StaticShapeData(DeployedTree7) : DeployedTree { + shapeFile = "dorg18.dts"; +}; + +datablock StaticShapeData(DeployedTree8) : DeployedTree { + shapeFile = "dorg19.dts"; +}; + +datablock StaticShapeData(DeployedTree9) : DeployedTree { + shapeFile = "porg3.dts"; +}; + +datablock StaticShapeData(DeployedTree10) : DeployedTree { + shapeFile = "porg6.dts"; +}; + +datablock StaticShapeData(DeployedTree11) : DeployedTree { + shapeFile = "sorg20.dts"; +}; + +datablock StaticShapeData(DeployedTree12) : DeployedTree { + shapeFile = "sorg22.dts"; +}; + +datablock StaticShapeData(DeployedTree13) : DeployedTree { + shapeFile = "xorg3.dts"; +}; + +datablock ShapeBaseImageData(TreeDeployableImage) { + mass = 1; + emap = true; + shapeFile = "stackable1s.dts"; + item = TreeDeployable; + mountPoint = 1; + offset = "0 0 0"; + deployed = DeployedTree; + heatSignature = 0; + + stateName[0] = "Idle"; + stateTransitionOnTriggerDown[0] = "Activate"; + + stateName[1] = "Activate"; + stateScript[1] = "onActivate"; + stateTransitionOnTriggerUp[1] = "Idle"; + + isLarge = true; + maxDepSlope = 360; + deploySound = ItemPickupSound; + + minDeployDis = 0.5; + maxDeployDis = 50.0; +}; + +datablock ItemData(TreeDeployable) { + className = Pack; + catagory = "Deployables"; + shapeFile = "stackable1s.dts"; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 1; + rotate = true; + image = "TreeDeployableImage"; + pickUpName = "a tree pack"; + heatSignature = 0; + emap = true; + }; + +function TreeDeployableImage::testObjectTooClose(%item) { + return ""; +} + +function TreeDeployableImage::testNoTerrainFound(%item) { + // don't check this for non-Landspike turret deployables +} + +function TreeDeployable::onPickup(%this, %obj, %shape, %amount) { + // created to prevent console errors +} + +function TreeDeployableImage::onDeploy(%item, %plyr, %slot) { + %className = "StaticShape"; + + %playerVector = vectorNormalize(-1 * getWord(%plyr.getEyeVector(),1) SPC getWord(%plyr.getEyeVector(),0) SPC "0"); + %item.surfaceNrm2 = %playerVector; + %rot = fullRot(%item.surfaceNrm,%item.surfaceNrm2); + + %deplObj = new (%className)() { + dataBlock = %item.deployed @ %plyr.packSet; + scale = vectorScale("1 1 1",$expertSetting["tree",%plyr.expertSet]); + }; + + // set orientation + %deplObj.setTransform(%item.surfacePt SPC %rot); + + // set the recharge rate right away + if (%deplObj.getDatablock().rechargeRate) + %deplObj.setRechargeRate(%deplObj.getDatablock().rechargeRate); + + // set team, owner, and handle + %deplObj.team = %plyr.client.Team; + %deplObj.setOwner(%plyr); + + // place the deployable in the MissionCleanup/Deployables group (AI reasons) + addToDeployGroup(%deplObj); + + //let the AI know as well... + AIDeployObject(%plyr.client, %deplObj); + + // play the deploy sound + serverPlay3D(%item.deploySound, %deplObj.getTransform()); + + // increment the team count for this deployed object + $TeamDeployedCount[%plyr.team, %item.item]++; + + addDSurface(%item.surface,%deplObj); + + // take the deployable off the player's back and out of inventory + %plyr.unmountImage(%slot); + %plyr.decInventory(%item.item, 1); + + return %deplObj; +} + +function DeployedTree::onDestroyed(%this,%obj,%prevState) { + if (%obj.isRemoved) + return; + %obj.isRemoved = true; + Parent::onDestroyed(%this,%obj,%prevState); + $TeamDeployedCount[%obj.team, TreeDeployable]--; + remDSurface(%obj); + %obj.schedule(500, "delete"); +} + +function TreeDeployableImage::onMount(%data, %obj, %node) { + %obj.hasTree = true; // set for treecheck + %obj.packSet = 0; + %obj.expertSet = 5; +} + +function TreeDeployableImage::onUnmount(%data, %obj, %node) { + %obj.hasTree = ""; + %obj.packSet = 0; + %obj.expertSet = 0; +} + +function DeployedTree0::onDestroyed(%this,%obj,%prevState) { + DeployedTree::onDestroyed(%this,%obj,%prevState); +} + +function DeployedTree1::onDestroyed(%this,%obj,%prevState) { + DeployedTree::onDestroyed(%this,%obj,%prevState); +} + +function DeployedTree2::onDestroyed(%this,%obj,%prevState) { + DeployedTree::onDestroyed(%this,%obj,%prevState); +} + +function DeployedTree3::onDestroyed(%this,%obj,%prevState) { + DeployedTree::onDestroyed(%this,%obj,%prevState); +} + +function DeployedTree4::onDestroyed(%this,%obj,%prevState) { + DeployedTree::onDestroyed(%this,%obj,%prevState); +} + +function DeployedTree5::onDestroyed(%this,%obj,%prevState) { + DeployedTree::onDestroyed(%this,%obj,%prevState); +} + +function DeployedTree6::onDestroyed(%this,%obj,%prevState) { + DeployedTree::onDestroyed(%this,%obj,%prevState); +} + +function DeployedTree7::onDestroyed(%this,%obj,%prevState) { + DeployedTree::onDestroyed(%this,%obj,%prevState); +} + +function DeployedTree8::onDestroyed(%this,%obj,%prevState) { + DeployedTree::onDestroyed(%this,%obj,%prevState); +} + +function DeployedTree9::onDestroyed(%this,%obj,%prevState) { + DeployedTree::onDestroyed(%this,%obj,%prevState); +} + +function DeployedTree10::onDestroyed(%this,%obj,%prevState) { + DeployedTree::onDestroyed(%this,%obj,%prevState); +} + +function DeployedTree11::onDestroyed(%this,%obj,%prevState) { + DeployedTree::onDestroyed(%this,%obj,%prevState); +} + +function DeployedTree12::onDestroyed(%this,%obj,%prevState) { + DeployedTree::onDestroyed(%this,%obj,%prevState); +} + +function DeployedTree13::onDestroyed(%this,%obj,%prevState) { + DeployedTree::onDestroyed(%this,%obj,%prevState); +} diff --git a/scripts/packs/tripwire.cs b/scripts/packs/tripwire.cs new file mode 100644 index 0000000..33234a1 --- /dev/null +++ b/scripts/packs/tripwire.cs @@ -0,0 +1,393 @@ +// Tripwire + +datablock ForceFieldBareData(TripField) : DeployedForceField { + baseTranslucency = 0.1; + powerOffTranslucency = 0.0; + teamPermiable = true; + otherPermiable = true; + color = "1 0 0"; + powerOffColor = "0.0 0.0 0.0"; + deployedFrom = ""; + needsPower = false; +}; + +datablock AudioProfile(TripwireSound) { + filename = "fx/misc/rolechange.wav"; + description = AudioClosest3d; + preload = true; +}; + +datablock TriggerData(TripTrigger) { + // TODO - check this + tickPeriodMS = 200; +}; + +function TripTrigger::onEnterTrigger(%data, %obj, %colObj) { +// TODO - keep trip FF scaled down until trip is triggered - vehicle fix? + %baseObj = %obj.baseObj; + %baseObj.triggerCount++; + if (%baseObj.triggerCount > 1) + return; + %baseObj.play3D(TripwireSound); + if (isObject(%baseObj.tripField)) { + cancel(%baseObj.tripField.hideSched); + %baseObj.tripField.getDataBlock().gainPower(%baseObj.tripField); + } + %tripMode = %baseObj.tripMode; + while (%tripMode > 1 && %tripMode > -1 && %tripMode !$= "") + %tripMode = %tripMode - 2; + %count = getWordCount($PowerList); + for(%i=0;%i<%count;%i++) { + %powerObj = getWord($PowerList,%i); + if (vectorDist(%baseObj.getPosition(),%powerObj.getPosition()) < %baseObj.switchRadius + && !%powerObj.isRemoved && %baseObj.powerFreq == %powerObj.powerFreq + && %baseObj.team == %powerObj.team) { + %r = toggleGenerator(%powerObj,!%tripMode); + %r1 = firstWord(%r); + %r2 = getTaggedString(getWord(%r,1)); + %r3 = getWord(%r,2); + if (%r1 == -3) { + cancel(%powerObj.toggleSched); + %powerObj.toggleSched = schedule(%r3 + 100,0,toggleGenerator,%powerObj,!%tripMode); + } + } + } +} + +function TripTrigger::onLeaveTrigger(%data, %obj, %colObj) { + %baseObj = %obj.baseObj; + %baseObj.triggerCount--; + if (%baseObj.triggerCount > 0) + return; + %baseObj.play3D(TripwireSound); + if (isObject(%baseObj.tripField)) { + cancel(%baseObj.tripField.hideSched); + %baseObj.tripField.hideSched = %baseObj.tripField.getDataBlock().schedule(2000,losePower,%baseObj.tripField); + } + %tripMode = %baseObj.tripMode; + if (%tripMode == 2 || %tripMode == 3) + return; + if (%tripMode == 4 || %tripMode == 5) + %timed = true; + while (%tripMode > 1 && %tripMode > -1 && %tripMode !$= "") + %tripMode = %tripMode - 2; + %count = getWordCount($PowerList); + for(%i=0;%i<%count;%i++) { + %powerObj = getWord($PowerList,%i); + if (vectorDist(%baseObj.getPosition(),%powerObj.getPosition()) < %baseObj.switchRadius + && !%powerObj.isRemoved && %baseObj.powerFreq == %powerObj.powerFreq + && %baseObj.team == %powerObj.team) { + if (%timed) { + cancel(%powerObj.toggleSched); + %powerObj.toggleSched = schedule(5000,0,delayedToggleGenerator,%powerObj,%tripMode); + } + else { + %r = toggleGenerator(%powerObj,%tripMode); + %r1 = firstWord(%r); + %r2 = getTaggedString(getWord(%r,1)); + %r3 = getWord(%r,2); + if (%r1 == -3) { + cancel(%powerObj.toggleSched); + %powerObj.toggleSched = schedule(%r3 + 100,0,toggleGenerator,%powerObj,%tripMode); + } + } + } + } +} + +function delayedToggleGenerator(%powerObj,%tripMode) { + %r = toggleGenerator(%powerObj,%tripMode); + %r1 = firstWord(%r); + %r2 = getTaggedString(getWord(%r,1)); + %r3 = getWord(%r,2); + if (%r1 == -3) { + cancel(%powerObj.toggleSched); + %powerObj.toggleSched = schedule(%r3 + 100,0,toggleGenerator,%powerObj,%tripMode); + } +} + +function TripTrigger::onTickTrigger(%data, %obj) { +} + +function TripTrigger::onTrigger(%this, %triggerId, %on) { +} + +datablock StaticShapeData(DeployedTripwire) : StaticShapeDamageProfile { + className = "tripwire"; + shapeFile = "camera.dts"; + + maxDamage = 0.2; + destroyedLevel = 0.2; + disabledLevel = 0.2; + + isShielded = false; + energyPerDamagePoint = 40; + maxEnergy = 30; + rechargeRate = 0.05; + + explosion = HandGrenadeExplosion; + expDmgRadius = 1.0; + expDamage = 0.3; + expImpulse = 500; + + dynamicType = $TypeMasks::StaticShapeObjectType; + deployedObject = true; + cmdCategory = "DSupport"; + cmdIcon = CMDSensorIcon; + cmdMiniIconName = "commander/MiniIcons/com_deploymotionsensor"; + targetNameTag = 'Deployed'; + targetTypeTag = 'Tripwire'; + deployAmbientThread = true; + debrisShapeName = "debris_generic_small.dts"; + debris = DeployableDebris; + heatSignature = 0; + emap = true; +}; + +datablock ShapeBaseImageData(TripwireDeployableImage) { + mass = 1; + emap = true; + shapeFile = "camera.dts"; + item = TripwireDeployable; + mountPoint = 1; + offset = "0 0 0"; + rotation = "-1 0 0 90"; + deployed = DeployedTripwire; + heatSignature = 0; + + stateName[0] = "Idle"; + stateTransitionOnTriggerDown[0] = "Activate"; + + stateName[1] = "Activate"; + stateScript[1] = "onActivate"; + stateTransitionOnTriggerUp[1] = "Idle"; + + isLarge = false; + maxDepSlope = 360; + deploySound = ItemPickupSound; + + minDeployDis = 0.25; + maxDeployDis = 5; +}; + +datablock ItemData(TripwireDeployable) { + className = Pack; + catagory = "Deployables"; + shapeFile = "stackable1s.dts"; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 3; + rotate = true; + image = "TripwireDeployableImage"; + pickUpName = "a tripwire pack"; + heatSignature = 0; + emap = true; +}; + +function TripwireDeployableImage::testNoTerrainFound(%item) { + // don't check this for non-Landspike turret deployables +} + +function TripwireDeployable::onPickup(%this, %obj, %shape, %amount) { + // created to prevent console errors +} + +function TripwireDeployableImage::onDeploy(%item, %plyr, %slot) { + %className = "StaticShape"; + + %playerVector = vectorNormalize(-1 * getWord(%plyr.getEyeVector(),1) SPC getWord(%plyr.getEyeVector(),0) SPC "0"); + + if (%item.surfaceinher == 0) { + if (vAbs(floorVec(%item.surfaceNrm,100)) $= "0 0 1") + %item.surfaceNrm2 = %playerVector; + else + %item.surfaceNrm2 = vectorNormalize(vectorCross(%item.surfaceNrm,"0 0 1")); + } + + %rot = fullRot(%item.surfaceNrm,%item.surfaceNrm2); + + %deplObj = new (%className)() { + dataBlock = DeployedTripwire; + }; + + %deplObj.switchRadius = getWord($packSetting["tripwire",%plyr.packSet],0); + %deplObj.fieldMode = getWord($packSetting["tripwire",%plyr.packSet],1); + %deplObj.tripMode = %plyr.expertSet; + if (%deplObj.fieldMode == 1) + %deplObj.beamRange = 160; + else + %deplObj.beamRange = 30; + + %deplObj.tripField = new ForceFieldBare() { + dataBlock = TripField; + scale = "0.05 0.05 0.1"; + }; + + %deplObj.tripField.pzone.delete(); + + %deplObj.tripTrigger = new Trigger() { + dataBlock = TripTrigger; + polyhedron = "0 1 0 1 0 0 0 -1 0 0 0 1"; + scale = "0.05 0.05 0.1"; + }; + + %deplObj.tripTrigger.baseObj = %deplObj; + + // set orientation + %deplObj.setTransform(%item.surfacePt SPC %rot); + adjustTripwire(%deplObj); + + // set the recharge rate right away + if (%deplObj.getDatablock().rechargeRate) + %deplObj.setRechargeRate(%deplObj.getDatablock().rechargeRate); + + // set team, owner, and handle + %deplObj.team = %plyr.client.Team; + %deplObj.setOwner(%plyr); + + // set power frequency + %deplObj.powerFreq = %plyr.powerFreq; + setTargetName(%deplObj.target,addTaggedString("Frequency" SPC %deplObj.powerFreq)); + + // set the sensor group if it needs one + if (%deplObj.getTarget() != -1) + setTargetSensorGroup(%deplObj.getTarget(), %plyr.client.team); + + // place the deployable in the MissionCleanup/Deployables group (AI reasons) + addToDeployGroup(%deplObj); + + //let the AI know as well... + AIDeployObject(%plyr.client, %deplObj); + + // play the deploy sound + serverPlay3D(%item.deploySound, %deplObj.getTransform()); + + // increment the team count for this deployed object + $TeamDeployedCount[%plyr.team, %item.item]++; + + %deplObj.deploy(); + + addDSurface(%item.surface,%deplObj); + + // take the deployable off the player's back and out of inventory + %plyr.unmountImage(%slot); + %plyr.decInventory(%item.item, 1); + + return %deplObj; +} + +function DeployedTripwire::onDestroyed(%this,%obj,%prevState) { + if (%obj.isRemoved) + return; + %obj.isRemoved = true; + Parent::onDestroyed(%this,%obj,%prevState); + $TeamDeployedCount[%obj.team, TripwireDeployable]--; + remDSurface(%obj); + %obj.schedule(500, "delete"); + if (isObject(%obj.tripField)) + %obj.tripField.schedule(500, "delete"); + if (isObject(%obj.tripTrigger)) + %obj.tripTrigger.schedule(500, "delete"); +} + +function DeployedTripwire::disassemble(%data,%plyr,%obj) { + if (isObject(%obj.tripField)) + %obj.tripField.delete(); + if (isObject(%obj.tripTrigger)) + %obj.tripTrigger.delete(); + disassemble(%data,%plyr,%obj); +} + +function adjustTripwire(%obj) { + if (!isObject(%obj)) + return; + cancel(%obj.adjustSched); + %pos = %obj.getPosition(); + %nrm = realVec(%obj,"0 0 1"); + %nrm2 = realVec(%obj,"1 0 0"); + %nrm3 = realVec(%obj,"0 1 0"); + + // TODO - temporary - remove + if ($TripWireFlareMode == true) { + %pos = vectorAdd(%obj.getPosition(),vectorScale(%nrm,0.35)); + %vec = vectorScale(%nrm,0.7); + %p = new FlareProjectile() { + dataBlock = FlareGrenadeProj; + initialDirection = %vec; + initialPosition = %pos; + sourceObject = %obj; + sourceSlot = 0; + }; + FlareSet.add(%p); + MissionCleanup.add(%p); + %p.schedule(6000,"delete"); + } + + // save ourselves re-doing some calculations + %mask = $TypeMasks::VehicleObjectType | $TypeMasks::StationObjectType | $TypeMasks::GeneratorObjectType | $TypeMasks::SensorObjectType | $TypeMasks::TurretObjectType | $TypeMasks::TerrainObjectType | $TypeMasks::InteriorObjectType | $TypeMasks::StaticObjectType | $TypeMasks::MoveableObjectType | $TypeMasks::DamagableItemObjectType; + if (%obj.fieldMode == 1) { + // new pad data can be done here for both field and trigger + // "normal" (no hit) beamRange limited to 0.5m - 8m + // max beamRange limited to 0.5m - 160m + %pad = pad(%obj.getPosition() SPC realVec(%obj,"0 0 1") SPC realVec(%obj,"1 0 0"),0.5 SPC limit(%obj.beamRange,0.5,8) SPC limit(%obj.beamRange,0.5,160),"-0.5 -0.5 -0.5",%mask,%obj.tripField); + %newScale = getWords(%pad,0,2); + %newPos = getWords(%pad,3,5); + %newRot = getWords(%pad,6,9); + } + else { + // beam + %dist = rayDist(vectorAdd(%pos,vectorScale(%nrm,0.1)) SPC %nrm,1 SPC %obj.beamRange SPC %obj.beamRange,%mask,%obj.tripField); + } + + if (isObject(%obj.tripField)) { + %obj2 = %obj.tripField; + if (%obj.fieldMode == 0) { + %scale = %obj2.getScale(); + %newPos = vectorAdd(%pos,vectorAdd(vectorScale(%nrm2,-(getWord(%scale,0) / 2)),vectorScale(%nrm3,-(getWord(%scale,1) / 2)))); + %newRot = %obj.getRotation(); + %newScale = getWords(%scale,0,1) SPC %dist; + } + %oldData = %obj2.oldData; + %newData = %newPos SPC %newRot SPC %newScale; + if (%oldData !$= %newData && %obj.triggerCount == 0) { + // call gainPower() before modifying forcefield! + %obj2.getDataBlock().gainPower(%obj2); + %obj2.setTransform(%newPos SPC %newRot); + %obj2.setScale(%newScale); + %obj2.oldData = %newData; + cancel(%obj2.hideSched); + %obj2.hideSched = %obj2.getDataBlock().schedule(2000,losePower,%obj2); + } + } + if (isObject(%obj.tripTrigger)) { + %obj2 = %obj.tripTrigger; + if (%obj.fieldMode == 0) { + %scale = %obj2.getScale(); + %newPos = vectorAdd(%pos,vectorAdd(vectorScale(%nrm2,-(getWord(%scale,0) / 2)),vectorScale(%nrm3,-(getWord(%scale,1) / 2)))); + %newRot = %obj.getRotation(); + %newScale = getWords(%scale,0,1) SPC %dist; + } + %oldData = %obj2.oldData; + %newData = %newPos SPC %newRot SPC %newScale; + if (%oldData !$= %newData && %obj.triggerCount == 0) { + %obj2.setTransform(%newPos SPC %newRot); + %obj2.setScale(%newScale); + %obj2.oldData = %newData; + } + } + %obj.adjustSched = schedule(1000,0,adjustTripwire,%obj); +} + +function TripwireDeployableImage::onMount(%data, %obj, %node) { + %obj.hasTripwire = true; // set for tripcheck + %obj.packSet = 2; + %obj.expertSet = 0; + displayPowerFreq(%obj); +} + +function TripwireDeployableImage::onUnmount(%data, %obj, %node) { + %obj.packSet = 0; + %obj.expertSet = 0; + %obj.hasTripwire = ""; +} diff --git a/scripts/packs/turretpack.cs b/scripts/packs/turretpack.cs new file mode 100644 index 0000000..9474c14 --- /dev/null +++ b/scripts/packs/turretpack.cs @@ -0,0 +1,141 @@ +// turretpack.cs - turret pack +// + +datablock ShapeBaseImageData(TurretDeployableImage) +{ +mass = 1; +emap = true; + +shapeFile = "stackable1s.dts"; +item = TurretBasePack; +mountPoint = 1; +offset = "0 -0.2 0"; + +minDeployDis = 0.5; +maxDeployDis = 5.0; + +deployed = TurretDeployedBase; +heatSignature = 0; + +stateName[0] = "Idle"; +stateTransitionOnTriggerDown[0] = "Activate"; + + + +stateName[1] = "Activate"; +stateScript[1] = "onActivate"; +stateTransitionOnTriggerUp[1] = "Idle"; + +isLarge = true; +maxDepSlope = 360; +deploySound = StationDeploySound; +}; + +datablock ItemData(TurretBasePack) +{ +className = Pack; +catagory = "Deployables"; +shapeFile = "stackable1s.dts"; +mass = 1; +elasticity = 0.2; +friction = 0.6; +pickupRadius = 1; +rotate = false; +image = "TurretDeployableImage"; +pickUpName = "a base turret pack"; +heatSignature = 0; + +computeCRC = true; +emap = true; + +}; + +datablock TurretData(TurretDeployedBase) : TurretDamageProfile +{ +className = DeployedTurret; +shapeFile = "turret_base_large.dts"; + +rechargeRate = 0.31; + +selfPower = true; + +needsPower = true; +mass = 1; +maxDamage = 2.25; +destroyedLevel = 2.25; +disabledLevel = 1.35; +repairRate = 0; +explosion = TurretExplosion; +expDmgRadius = 15.0; +expDamage = 0.7; +expImpulse = 2000.0; + +deployedObject = true; + +thetaMin = 15; +thetaMax = 140; +//thetaNull = 90; + +isShielded = true; +energyPerDamagePoint = 50; +maxEnergy = 150; + +humSound = SensorHumSound; +heatSignature = 1; +pausePowerThread = true; + +canControl = true; +cmdCategory = "DTactical"; +cmdIcon = CMDTurretIcon; +cmdMiniIconName = "commander/MiniIcons/com_turret_grey"; +targetNameTag = 'Deployed Base'; +targetTypeTag = 'Turret'; +sensorData = TurretBaseSensorObj; +sensorRadius = TurretBaseSensorObj.detectRadius; +sensorColor = "0 212 45"; + +firstPersonOnly = true; + +debrisShapeName = "debris_generic.dts"; +debris = TurretDebris; +}; + +function TurretBasePack::onPickup(%this, %obj, %shape, %amount) +{ +// created to prevent console errors +} + +function TurretDeployableImage::onDeploy(%item, %plyr, %slot) +{ +%deplObj = Parent::onDeploy(%item, %plyr, %slot); +%origBarrel = %item.item.origBarrel; +if(%origBarrel !$= "") +{ +%deplObj.mountImage(%origBarrel, 0, false); +%item.item.origBarrel = ""; +} +%playerVector = vectorNormalize(getWord(%plyr.getEyeVector(),1) SPC -1 * getWord(%plyr.getEyeVector(),0) SPC "0"); + +%item.surfacenrm = VectorNormalize(%item.surfacenrm); +//echo(%playervector); +if (vAbs(floorVec(%item.surfaceNrm,100)) $= "0 0 1") + %item.surfaceNrm2 = vectorScale(%playerVector,1); + else + %item.surfaceNrm2 = vectorNormalize(vectorCross(%item.surfaceNrm,"0 0 1")); + + %rot = fullRot(%item.surfaceNrm,%item.surfaceNrm2); + +%deplObj.setTransform(%item.surfacePt SPC %rot); +//%deplObj.setSelfPowered(); +//%deplObj.playThread($PowerThread,"Power"); + +addDSurface(%item.surface,%deplObj); +addToDeployGroup(%deplObj); +%deplObj.powerFreq = %plyr.powerFreq; +%deplObj.team = %plyr.team; +checkPowerObject(%deplObj); +} + +function TurretDeployableImage::onMount(%data, %obj, %node) { + displayPowerFreq(%obj); +} diff --git a/scripts/packs/vehiclepad.cs b/scripts/packs/vehiclepad.cs new file mode 100644 index 0000000..29f1246 --- /dev/null +++ b/scripts/packs/vehiclepad.cs @@ -0,0 +1,764 @@ +//====================================== +// made by dynablade +//====================================== Deployable Vehicle Pad + + +datablock StaticShapeData(DeployableVehicleStation) : StaticShapeDamageProfile +{ +className = Station; +catagory = "Stations"; +shapeFile = "Vehicle_pad_station.dts"; +maxDamage = 7.5; +destroyedLevel = 7.5; +disabledLevel = 7.5; +explosion = ShapeExplosion; +expDmgRadius = 10.0; +expDamage = 0.4; +expImpulse = 1500.0; +dynamicType = $TypeMasks::StationObjectType; +isShielded = true; +energyPerDamagePoint = 500; +maxEnergy = 250; +rechargeRate = 0.31; +humSound = StationVehicleHumSound; + +cmdCategory = "Support"; +cmdIcon = CMDVehicleStationIcon; +cmdMiniIconName = "commander/MiniIcons/com_vehicle_pad_inventory"; +targetTypeTag = 'Deployable Vehicle Station'; + +debrisShapeName = "debris_generic.dts"; +debris = StationDebris; +needsPower = true; +}; + +datablock StaticShapeData(DeployableVehiclePad) +{ +className = vpad; +catagory = "Stations"; +shapeFile = "Vehicle_pad.dts"; +maxDamage = 7.5; +destroyedLevel = 7.5; +disabledLevel = 7.5; +explosion = ShapeExplosion; +expDmgRadius = 10.0; +expDamage = 0.4; +expImpulse = 1500.0; +rechargeRate = 0.05; +targetTypeTag = 'Deployable Vehicle Station'; +needsPower = true; +}; + +datablock StaticShapeData(DeployableVehiclePad2) : DeployableVehiclePad +{ +className = vpad; +shapeFile = "station_teleport.dts"; +}; + + + + +datablock StaticShapeData(DeployableVehiclePadBottom) : StaticShapeDamageProfile { + className = "floor"; + shapeFile = "bmiscf.dts"; + + maxDamage = 4; + destroyedLevel = 4; + disabledLevel = 3.5; + + isShielded = true; + energyPerDamagePoint = 30; + maxEnergy = 200; + rechargeRate = 0.25; + + explosion = HandGrenadeExplosion; + expDmgRadius = 3.0; + expDamage = 0.1; + expImpulse = 200.0; + + dynamicType = $TypeMasks::StaticShapeObjectType; + deployedObject = true; + cmdCategory = "DSupport"; + cmdIcon = CMDSensorIcon; + cmdMiniIconName = "commander/MiniIcons/com_deploymotionsensor"; + targetNameTag = 'Medium Blast floor'; + deployAmbientThread = true; + debrisShapeName = "debris_generic_small.dts"; + debris = DeployableDebris; + heatSignature = 0; + needsPower = true; +}; + +datablock StaticShapeData(PotPipe) : DeployableVehiclePadBottom +{ +shapeFile = "silver_pole.dts"; +targetNameTag = 'Pot Powered'; +targetTypeTag = 'Alloy forge'; +}; + +datablock ParticleData(DVPADP) +{ + dragCoeffiecient = 0.0; + gravityCoefficient = 0.0; + inheritedVelFactor = 0.0; + + lifetimeMS = 1500; + lifetimeVarianceMS = 0; + + spinRandomMin = 30.0; + spinRandomMax = 30.0; + windcoefficient = 0; + textureName = "skins/jetflare03"; + + colors[0] = "0.3 0.3 1.0 0.1"; + colors[1] = "0.3 0.3 1.0 1"; + colors[2] = "0.3 0.3 1.0 1"; + colors[3] = "0.3 0.3 1.0 0.1"; + + sizes[0] = 5; + sizes[1] = 5; + sizes[2] = 5; + sizes[3] = 5; + + times[0] = 0.25; + times[1] = 0.5; + times[2] = 0.75; + times[3] = 1; + +}; + +datablock ParticleEmitterData(DVPADE) +{ + lifetimeMS = 10; + ejectionPeriodMS = 10; + periodVarianceMS = 0; + + ejectionVelocity = 0.01; + velocityVariance = 0.0; + ejectionoffset = 8; + thetaMin = 80.0; + thetaMax = 100.0; + + phiReferenceVel = "180"; + phiVariance = "5"; + orientParticles = false; + orientOnVelocity = false; + + particles = "DVPADP"; +}; + +datablock ParticleData(SIGMAP) +{ + dragCoeffiecient = 0.0; + gravityCoefficient = -0.5; + inheritedVelFactor = 0.0; + + lifetimeMS = 1500; + lifetimeVarianceMS = 1000; + + spinRandomMin = -30.0; + spinRandomMax = 30.0; + windcoefficient = 0; + textureName = "skins/jetflare03"; + + colors[0] = "1 1 0 0"; //Wacky collors :P + colors[1] = "0 1 1 1"; + colors[2] = "1 0 1 1"; + colors[3] = "0 1 0 1"; + + sizes[0] = 5; + sizes[1] = 5; + sizes[2] = 5; + sizes[3] = 5; + + times[0] = 0.5; + times[1] = 0.6; + times[2] = 0.8; + times[3] = 1; + +}; + +datablock ParticleEmitterData(SIGMAE) +{ + lifetimeMS = 10; + ejectionPeriodMS = 50; + periodVarianceMS = 0; + + ejectionVelocity = 1.0; + velocityVariance = 0.5; + ejectionoffset = 0.5; + thetaMin = 80.0; + thetaMax = 100.0; + + phiReferenceVel = "0"; + phiVariance = "360"; + orientParticles = false; + orientOnVelocity = false; + + particles = "SIGMAP"; +}; + + +function DeployableVehicleStation::onAdd(%this, %obj) +{ +Parent::onAdd(%this, %obj); + +%obj.setRechargeRate(%obj.getDatablock().rechargeRate); +%trigger = new Trigger() +{ +dataBlock = stationTrigger; +polyhedron = "-0.75 0.75 0.0 1.5 0.0 0.0 0.0 -1.5 0.0 0.0 0.0 2.0"; +}; +MissionCleanup.add(%trigger); +%trigger.setTransform(%obj.getTransform()); +%trigger.station = %obj; +%obj.trigger = %trigger; +} + +function DeployableVehicleStation::stationReady(%data, %obj) +{ +// Make sure none of the other popup huds are active: +messageClient( %obj.triggeredBy.client, 'CloseHud', "", 'scoreScreen' ); +messageClient( %obj.triggeredBy.client, 'CloseHud', "", 'inventoryScreen' ); + +//Display the Vehicle Station GUI +commandToClient(%obj.triggeredBy.client, 'StationVehicleShowHud'); +} + +function DeployableVehicleStation::stationFinished(%data, %obj) +{ +//Hide the Vehicle Station GUI +commandToClient(%obj.triggeredBy.client, 'StationVehicleHideHud'); +} + +function DeployableVehicleStation::getSound(%data, %forward) +{ +if(%forward) +return "StationVehicleAcitvateSound"; +else +return "StationVehicleDeactivateSound"; +} + +function DeployableVehicleStation::setPlayersPosition(%data, %obj, %trigger, %colObj) +{ +%vel = getWords(%colObj.getVelocity(), 0, 1) @ " 0"; +if((VectorLen(%vel) < 22) && (%obj.triggeredBy != %colObj)) +{ +%posXY = getWords(%trigger.getTransform(),0 ,1); +%posZ = getWord(%trigger.getTransform(), 2); +%rotZ = getWord(%obj.getTransform(), 5); +%angle = getWord(%obj.getTransform(), 6); +%angle += 3.141592654; +if(%angle > 6.283185308) +%angle = %angle - 6.283185308; +%colObj.setvelocity("0 0 0"); +%colObj.setTransform(%posXY @ " " @ %posZ + 0.2 @ " " @ "0 0 " @ %rotZ @ " " @ %angle );//center player on object +return true; +} +return false; +} + +function DeployableVehiclePad::onAdd(%this, %obj) +{ +Parent::onAdd(%this, %obj); + +%obj.ready = true; +%obj.setRechargeRate(%obj.getDatablock().rechargeRate); +} + +function DeployableVehiclePad2::onAdd(%this, %obj) +{ +Parent::onAdd(%this, %obj); + +%obj.ready = true; +%obj.setRechargeRate(%obj.getDatablock().rechargeRate); +} + + +function GiveStation(%obj,%transform) +{ +%pos = getWords(%transform,0,2); +%rot = getWords(%transform,3,5) SPC (getWord(%transform,6)/3.14*180); +%sv = new StaticShape() +{ +scale = "1 1 1"; +dataBlock = DeployableVehicleStation; +lockCount = "0"; +homingCount = "0"; +team = %obj.team; +position = %pos; +rotation = %rot; +}; + +%sv.setTransform(%transform); +%sv.powerFreq = %obj.powerFreq; +MissionCleanup.add(%sv); +//%sv.getDataBlock().gainPower(%sv); +//%obj.getDatablock().gainPower(%obj); +checkPowerObject(%obj); +checkPowerObject(%sv); +%sv.pad = %obj; +%obj.station = %sv; +%sv.trigger.mainObj = %obj; +%sv.trigger.disableObj = %sv; +adjustTrigger(%sv); + +//Remove unwanted vehicles +if(%obj.scoutVehicle !$= "Removed") +%sv.vehicle[scoutvehicle] = true; +if(%obj.assaultVehicle !$= "Removed") +%sv.vehicle[assaultVehicle] = true; +if(%obj.AlternateMobileBase !$= "Removed") +%sv.vehicle[AlternateMobileBase] = true; +if(%obj.mobileBaseVehicle !$= "Removed") // TeleToMPB(); +%sv.vehicle[mobileBasevehicle] = true; +if(%obj.PyroXL !$= "Removed") +%sv.vehicle[PyroXL] = true; +if(%obj.scoutFlyer !$= "Removed") +%sv.vehicle[scoutFlyer] = true; +if(%obj.bomberFlyer !$= "Removed") +%sv.vehicle[bomberFlyer] = true; +if(%obj.hapcFlyer !$= "Removed") +%sv.vehicle[hapcFlyer] = true; +if(%obj.hoverBike !$= "Removed") +%sv.vehicle[hoverBike] = true; +return %sv; +} + +function DeployableVehiclePad::onEndSequence(%data, %obj, %thread) +{ +if(%thread == $ActivateThread) +{ +%obj.ready = true; +%obj.stopThread($ActivateThread); +} +Parent::onEndSequence(%data, %obj, %thread); +} + +function DeployableVehiclePad2::onEndSequence(%data, %obj, %thread) +{ +if(%thread == $ActivateThread) +{ +%obj.ready = true; +%obj.stopThread($ActivateThread); +} +Parent::onEndSequence(%data, %obj, %thread); +} + +function DeployableVehiclePad::gainPower(%data, %obj) +{ +if (isObject(%obj.station)) + %obj.station.setSelfPowered(); +Parent::gainPower(%data, %obj); +} + +function DeployableVehiclePad2::gainPower(%data, %obj) +{ +if (isObject(%obj.station)) + %obj.station.setSelfPowered(); +Parent::gainPower(%data, %obj); +} + +function DeployableVehiclePad::losePower(%data, %obj) +{ +if (isObject(%obj.station)) + %obj.station.clearSelfPowered(); +Parent::losePower(%data, %obj); +} + +function DeployableVehiclePad2::losePower(%data, %obj) +{ +if (isObject(%obj.station)) + %obj.station.clearSelfPowered(); +Parent::losePower(%data, %obj); +} + +function DeployableVehiclePad::onDestroyed(%this, %obj, %prevState) +{ +if (isObject(%obj)) + disassembleVehilcepad(%obj,%plyr); +Parent::onDestroyed(%this, %obj, %prevState); +$TeamDeployedCount[%obj.team, VehiclePadPack]--; +%obj.schedule(500, "delete"); +%obj.station.schedule(500, "delete"); +%obj.back.schedule(500,"delete"); +} + +function DeployableVehiclePad2::onDestroyed(%this, %obj, %prevState) +{ +if (isObject(%obj)) + disassembleVehilcepad(%obj,%plyr); +Parent::onDestroyed(%this, %obj, %prevState); +$TeamDeployedCount[%obj.team, VehiclePadPack]--; +%obj.schedule(500, "delete"); +%obj.station.schedule(500, "delete"); +%obj.back.schedule(500,"delete"); +} + + + +function DeployableVehicleStation::onDestroyed(%this, %obj, %prevState) +{ +if (isObject(%obj.pad)) + disassembleVehilcepad(%obj.pad,%plyr); +Parent::onDestroyed(%this, %obj, %prevState); +$TeamDeployedCount[%obj.team, VehiclePadPack]--; +%obj.schedule(500, "delete"); +%obj.station.schedule(500, "delete"); +%obj.back.schedule(500,"delete"); +} + +function DeployableVehiclePadBottom::onDestroyed(%this, %obj, %prevState) +{ +if (isObject(%obj.station)) + disassembleVehilcepad(%obj.station,%plyr); +Parent::onDestroyed(%this, %obj, %prevState); +$TeamDeployedCount[%obj.team, VehiclePadPack]--; +%obj.schedule(500, "delete"); +%obj.station.schedule(500, "delete"); +%obj.back.schedule(500,"delete"); +} + + + + +datablock ShapeBaseImageData(VehiclePadPackImage) +{ +mass = 1; +emap = true; + +shapeFile = "pack_deploy_inventory.dts"; +item = VehiclePadPack; +mountPoint = 1; +offset = "0 0 0"; +heatSignature = 0; +deployed = DeployableVehiclePad; + +stateName[0] = "Idle"; +stateTransitionOnTriggerDown[0] = "Activate"; + +stateName[1] = "Activate"; +stateScript[1] = "onActivate"; +stateTransitionOnTriggerUp[1] = "Idle"; + +maxDepSlope = 360; +deploySound = StationDeploySound; + +minDeployDis = 0; +maxDeployDis = 50.0; //meters from body + +}; + +datablock ItemData(VehiclePadPack) +{ +className = Pack; +catagory = "Deployables"; +shapeFile = "pack_deploy_inventory.dts"; +mass = 1; +elasticity = 0.2; +friction = 0.6; +pickupRadius = 1; +rotate = false; +image = "VehiclePadPackImage"; +pickUpName = "a deployable vehicle pad"; +heatSignature = 0; + +emap = true; +}; + +function VehiclePadPackImage::onMount(%this, %obj, %slot) +{ +%this.imagemount = %obj; +%obj.hasVehiclepad = 1; +} + +function VehiclePadPackImage::onUnmount(%data,%obj,%node) +{ +%obj.hasVehiclepad = ""; +} + +function VehiclePadPack::onPickup(%this, %pack, %player, %amount) +{ +%player.packcharge = %pack.charge; +%player.lastvpad = %pack.vpad; +} + + +function VehiclePadPack::onThrow(%this,%pack,%player) +{ + %this.charge = %player.packcharge; + %this.vpad = %player.lastvpad; + %player.packcharge = ""; + %player.lastvpad = ""; + serverPlay3D(ItemThrowSound, %player.getTransform()); + %pack.schedulePop(); +} + + + +function VehiclePadPackImage::onDeploy(%item, %plyr, %slot) +{ +if (IsObject(%plyr.lastvpad) && IsObject(%plyr.lastvpad.station)) + %plyr.packcharge = 0; +if (IsObject(%plyr.lastvpad) && !IsObject(%plyr.lastvpad.station)) + %plyr.packcharge = 1; +if (!IsObject(%plyr.lastvpad)) + %plyr.packcharge = 0; + + +// take the deployable off the player's back and out of inventory +if (%plyr.packcharge == 1) + { + %plyr.unmountImage(%slot); + %plyr.decInventory(%item.item, 1); + $TeamDeployedCount[%plyr.team, %item.item]++; + %playerVector = vectorNormalize(-1 * getWord(%plyr.getEyeVector(),1) SPC getWord(%plyr.getEyeVector(),0) SPC "0"); + if (vAbs(floorVec(%item.surfaceNrm,100)) $= "0 0 1") + %item.surfaceNrm2 = vectorScale(%playerVector,1); + else + %item.surfaceNrm2 = vectorNormalize(vectorCross(%item.surfaceNrm,"0 0 -1")); + + %rot = fullRot(%item.surfaceNrm,%item.surfaceNrm2); + %vpad = %plyr.lastvpad; + %deplObj = GiveStation(%vpad,%item.surfacePt SPC %rot); + %deplObj.deploy(); + addDSurface(%item.surface,%deplObj); + %deplObj.setOwner(%plyr); + %plyr.packcharge = ""; + %plyr.lastvpad = ""; + %vpad.isRemoved = 0; + %vpad.back.isRemoved = 0; + if (%vpad.style ==2) + { + %deplObj.emitter = CreateEmitter(%item.surfacePt,SIGMAE); + %deplObj.emitter.setRotation(%deplObj.getRotation()); + } + } +else + { + %dist = VectorSub(%item.surfacept,%plyr.getTransform()); + %nrm = VirVec(%item.surface,%item.surfacenrm); + %img = VirVec(%item.surface,VectorNormalize(VectorCross(VectorCross(%item.surfacenrm,%dist),%item.surfacenrm))); + %item.surfacenrm2 = realvec(%item.surface,VectorCross(%nrm,topvec(%img))); + // create the actual deployable + %rot = %item.getInitialRotation(%plyr); + + if (%plyr.packset == 1) + %block = DeployableVehiclePad2; + else + %block = DeployableVehiclePad; + + %deplObj = new StaticShape() + { + dataBlock = %block; + }; + %back = new StaticShape() + { + dataBlock = DeployableVehiclePadBottom; + }; + %back.needsfit = 1; + %deplObj.needsfit = 1; + %deplObj.style = %plyr.packset; + %pos = getWords(%item.surface.getEdge(%nrm),0,2); + %deplObj.setTransform(%pos SPC fullrot(%item.surfacenrm,%item.surfacenrm2)); + if (VectorDot(vAbs(VectorNormalize(topvec(%img))),%item.surface.getRealSize())== %item.surfacesizex) + { + %x= %item.surfacesizex; + %y= %item.surfacesizey; + %item.surfacesizex = %y; + %item.surfacesizey = %x; + } + %deplObj.setRealSize(%item.surfacesizex SPC %item.surfacesizey SPC "1.5"); + %back.setTransform(%pos SPC fullrot(%item.surfacenrm,%item.surfacenrm2)); + %back.setRealSize(VectorMultiply(%deplObj.getRealSize(),"1 1 0.1")); + if (%plyr.packset == 2) + { + %back.potpipes(); + } + // %deplObj.setTransform(modifyTransform(%pos SPC %rot, "0 0 -1 0 0 0 0")); + %deplObj.back = %back; + %back.station = %deplObj; + // set the recharge rate right away + if(%deplObj.getDatablock().rechargeRate) + %deplObj.setRechargeRate(%deplObj.getDatablock().rechargeRate); + + // set team, owner, and handle + %deplObj.team = %plyr.client.Team; + %back.team = %plyr.client.Team; + %deplObj.setOwner(%plyr); + %back.setOwner(%plyr); + + // set the sensor group if it needs one + if(%deplObj.getTarget() != -1) + setTargetSensorGroup(%deplObj.getTarget(), %plyr.client.team); + + // place the deployable in the MissionCleanup/Deployables group (AI reasons) + addToDeployGroup(%deplObj); + addToDeployGroup(%deplObj.back); + + //let the AI know as well... + AIDeployObject(%plyr.client, %deplObj); + + // play the deploy sound + serverPlay3D(%item.deploySound, %deplObj.getTransform()); + + // increment the team count for this deployed object + %deplObj.getDatablock().onAdd(%deplObj); + %deplObj.deploy(); + //%deplObj.setSelfPowered(); + %plyr.packcharge++; + %plyr.lastvpad = %deplObj; + %deplObj.powerFreq = %plyr.powerFreq; + %back.powerFreq = %plyr.powerFreq; + checkPowerObject(%deplobj); + checkPowerObject(%back); + %deplObj.isRemoved = 1; + %back.isRemoved = 1; + schedule(6000,0,"FadePad",%deplObj,%plyr); + addDSurface(%item.surface,%deplObj); + addDSurface(%item.surface,%back); + } +} + +function FadePad(%obj,%plyr) +{ +if (!Isobject(%obj.station)) + { + schedule(100,%obj,"disassembleVehilcepad",%obj,%plyr); + } +} + +function GameBase::PotPipes(%obj) +{ +%obj.pipe1 = new StaticShape() + { + dataBlock = PotPipe; + scale = "0.5 0.5 0.5"; + }; +%obj.pipe2 = new StaticShape() + { + dataBlock = PotPipe; + scale = "0.5 0.5 0.5"; + }; +%obj.pipe3 = new StaticShape() + { + dataBlock = PotPipe; + scale = "0.5 0.5 0.5"; + }; +%obj.pipe4 = new StaticShape() + { + dataBlock = PotPipe; + scale = "0.5 0.5 0.5"; + }; +%obj.pipe1.setTransform(%obj.getEdge("0.9 0.9 1") SPC %obj.getRotation()); +%obj.pipe2.setTransform(%obj.getEdge("0.9 -0.9 1")SPC %obj.getRotation()); +%obj.pipe3.setTransform(%obj.getEdge("-0.9 -0.9 1")SPC %obj.getRotation()); +%obj.pipe4.setTransform(%obj.getEdge("-0.9 0.9 1")SPC %obj.getRotation()); +%obj.pipe1.emitter = CreateEmitter(%obj.pipe1.getEdge("0 0 1"),HeavyDamageSmoke); +%obj.pipe2.emitter = CreateEmitter(%obj.pipe2.getEdge("0 0 1"),HeavyDamageSmoke); +%obj.pipe3.emitter = CreateEmitter(%obj.pipe3.getEdge("0 0 1"),HeavyDamageSmoke); +%obj.pipe4.emitter = CreateEmitter(%obj.pipe4.getEdge("0 0 1"),HeavyDamageSmoke); +addToDeployGroup(%obj.pipe1); +addToDeployGroup(%obj.pipe2); +addToDeployGroup(%obj.pipe3); +addToDeployGroup(%obj.pipe4); +} + +function GameBase::RemPotPipes(%obj) +{ +if (IsObject(%obj.pipe1)) +{ +%obj.pipe1.emitter.delete(); +%obj.pipe1.delete(); +} +if (IsObject(%obj.pipe2)) +{ +%obj.pipe2.emitter.delete(); +%obj.pipe2.delete(); +} +if (IsObject(%obj.pipe3)) +{ +%obj.pipe3.emitter.delete(); +%obj.pipe3.delete(); +} +if (IsObject(%obj.pipe4)) +{ +%obj.pipe4.emitter.delete(); +%obj.pipe4.delete(); +} +} + +function VehiclePadPackImage::testSurfaceTooNarrow(%item,%surface) +{ +%nrm = getWords(%item.surface,4,6); +%mask = invFace(%nrm); +%narrower = vectorMultiply(%mask,%item.surface.getRealSize()); +%fx = vectorNormalize(topVec(%narrower)); +%fy = VectorCross(%nrm,%fx); +%sx = VectorLen(VectorMultiply(%fx,%item.surface.getRealSize())); +%sy = VectorLen(VectorMultiply(%fy,%item.surface.getRealSize())); + +if (%sx < 17 || %sy < 17 || %sx < %sy*0.5 || %sy < %sx*0.5) + { + return !%item.imagemount.packcharge; + } +else + { + %item.surfacesizex = %sx; + %item.surfacesizey = %sy; + return false; + } +} + +function VehiclePadPackImage::testNoInteriorFound(%item,%surface) +{ +return !IsCubic(%item.surface) && !%item.imagemount.packcharge; +} + +function DeployableVehiclePad::disassemble(%data,%plyr,%obj) +{ +if (isObject(%obj)) + disassembleVehilcepad(%obj,%plyr); +disassemble(%data,%plyr,%obj); +} + +function DeployableVehiclePad2::disassemble(%data,%plyr,%obj) +{ +if (isObject(%obj)) + disassembleVehilcepad(%obj,%plyr); +disassemble(%data,%plyr,%obj); +} + +function DeployableVehicleStation::disassemble(%data,%plyr,%obj) +{ +if (isObject(%obj.pad)) + disassembleVehilcepad(%obj.pad,%plyr); +disassemble(%data,%plyr,%obj); +} + +function DeployableVehiclePadBottom::disassemble(%data,%plyr,%obj) +{ +if (isObject(%obj.station)) + disassembleVehilcepad(%obj.station,%plyr); +disassemble(%data,%plyr,%obj); +} + +function PotPipe::disassemble(%data,%plyr,%obj) +{ +if (%obj.emitter) + %obj.emitter.delete(); +disassemble(%data,%plyr,%obj); +} + +function disassembleVehilcepad(%station,%plyr) +{ +%station.back.rempotpipes(); +if (%station.station.emitter) + %station.station.emitter.delete(); +if (isObject(%station.station)) + disassemble("",%plyr,%station.station); + +if (isObject(%station.back)) + disassemble("",%plyr,%station.back); +disassemble("",%plyr,%station); +} diff --git a/scripts/player.cs b/scripts/player.cs new file mode 100644 index 0000000..b386fe5 --- /dev/null +++ b/scripts/player.cs @@ -0,0 +1,3693 @@ +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- + +$InvincibleTime = 6; + +// Load dts shapes and merge animations +exec("scripts/light_male.cs"); +exec("scripts/medium_male.cs"); +exec("scripts/heavy_male.cs"); +exec("scripts/light_female.cs"); +exec("scripts/medium_female.cs"); +exec("scripts/bioderm_light.cs"); +exec("scripts/bioderm_medium.cs"); +exec("scripts/bioderm_heavy.cs"); + +$CorpseTimeoutValue = 22 * 1000; + +//Damage Rate for entering Liquid +$DamageLava = 0.0325; +$DamageHotLava = 0.0325; +$DamageCrustyLava = 0.0325; + +$PlayerDeathAnim::TorsoFrontFallForward = 1; +$PlayerDeathAnim::TorsoFrontFallBack = 2; +$PlayerDeathAnim::TorsoBackFallForward = 3; +$PlayerDeathAnim::TorsoLeftSpinDeath = 4; +$PlayerDeathAnim::TorsoRightSpinDeath = 5; +$PlayerDeathAnim::LegsLeftGimp = 6; +$PlayerDeathAnim::LegsRightGimp = 7; +$PlayerDeathAnim::TorsoBackFallForward = 8; +$PlayerDeathAnim::HeadFrontDirect = 9; +$PlayerDeathAnim::HeadBackFallForward = 10; +$PlayerDeathAnim::ExplosionBlowBack = 11; + +datablock SensorData(PlayerSensor) +{ + detects = true; + detectsUsingLOS = true; + detectsPassiveJammed = true; + detectRadius = 2000; + detectionPings = false; + detectsFOVOnly = true; + detectFOVPercent = 1.3; + useObjectFOV = true; +}; + +//---------------------------------------------------------------------------- + +datablock EffectProfile(ArmorJetEffect) +{ + effectname = "armor/thrust"; + minDistance = 5.0; + maxDistance = 10.0; +}; + +datablock EffectProfile(ImpactSoftEffect) +{ + effectname = "armor/light_land_soft"; + minDistance = 5.0; + maxDistance = 10.0; +}; + +datablock EffectProfile(ImpactHardEffect) +{ + effectname = "armor/light_land_hard"; + minDistance = 5.0; + maxDistance = 10.0; +}; + +datablock EffectProfile(ImpactMetalEffect) +{ + effectname = "armor/light_land_metal"; + minDistance = 5.0; + maxDistance = 10.0; +}; + +datablock EffectProfile(ImpactSnowEffect) +{ + effectname = "armor/light_land_snow"; + minDistance = 5.0; + maxDistance = 10.0; +}; + +datablock EffectProfile(CorpseLootingEffect) +{ + effectname = "weapons/generic_switch"; + minDistance = 2.5; + maxDistance = 2.5; +}; + +datablock EffectProfile(MountVehicleEffect) +{ + effectname = "vehicles/mount_dis"; + minDistance = 5; + maxDistance = 20; +}; + +datablock EffectProfile(UnmountVehicleEffect) +{ + effectname = "weapons/generic_switch"; + minDistance = 5; + maxDistance = 20; +}; + +datablock EffectProfile(GenericPainEffect) +{ + effectname = "misc/generic_pain"; + minDistance = 2.5; + maxDistance = 2.5; +}; + +datablock EffectProfile(GenericDeathEffect) +{ + effectname = "misc/generic_death"; + minDistance = 2.5; + maxDistance = 2.5; +}; + +datablock EffectProfile(ImpactHeavyWaterEasyEffect) +{ + effectname = "armor/general_water_smallsplash"; + minDistance = 5; + maxDistance = 15; +}; + +datablock EffectProfile(ImpactHeavyMediumWaterEffect) +{ + effectname = "armor/general_water_medsplash"; + minDistance = 5; + maxDistance = 15; +}; + +datablock EffectProfile(ImpactHeavyWaterHardEffect) +{ + effectname = "armor/general_water_bigsplash"; + minDistance = 5; + maxDistance = 15; +}; + +//---------------------------------------------------------------------------- +//datablock AudioProfile( DeathCrySound ) +//{ +// fileName = ""; +// description = AudioClose3d; +// preload = true; +//}; +// +//datablock AudioProfile( PainCrySound ) +//{ +// fileName = ""; +// description = AudioClose3d; +// preload = true; +//}; + +datablock AudioProfile(ArmorJetSound) +{ + filename = "fx/armor/thrust.wav"; + description = CloseLooping3d; + preload = true; + effect = ArmorJetEffect; +}; + +datablock AudioProfile(ArmorWetJetSound) +{ + filename = "fx/armor/thrust_uw.wav"; + description = CloseLooping3d; + preload = true; + effect = ArmorJetEffect; +}; + +datablock AudioProfile(MountVehicleSound) +{ + filename = "fx/vehicles/mount_dis.wav"; + description = AudioClose3d; + preload = true; + effect = MountVehicleEffect; +}; + +datablock AudioProfile(UnmountVehicleSound) +{ + filename = "fx/vehicles/mount.wav"; + description = AudioClose3d; + preload = true; + effect = UnmountVehicleEffect; +}; + +datablock AudioProfile(CorpseLootingSound) +{ + fileName = "fx/weapons/generic_switch.wav"; + description = AudioClosest3d; + preload = true; + effect = CorpseLootingEffect; +}; + +datablock AudioProfile(ArmorMoveBubblesSound) +{ + filename = "fx/armor/bubbletrail2.wav"; + description = CloseLooping3d; + preload = true; +}; + +datablock AudioProfile(WaterBreathMaleSound) +{ + filename = "fx/armor/breath_uw.wav"; + description = ClosestLooping3d; + preload = true; +}; + +datablock AudioProfile(WaterBreathFemaleSound) +{ + filename = "fx/armor/breath_fem_uw.wav"; + description = ClosestLooping3d; + preload = true; +}; + +datablock AudioProfile(waterBreathBiodermSound) +{ + filename = "fx/armor/breath_bio_uw.wav"; + description = ClosestLooping3d; + preload = true; +}; + +datablock AudioProfile(SkiAllSoftSound) +{ + filename = "fx/armor/ski_soft.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(SkiAllHardSound) +{ + filename = "fx/armor/ski_soft.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(SkiAllMetalSound) +{ + filename = "fx/armor/ski_soft.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(SkiAllSnowSound) +{ + filename = "fx/armor/ski_soft.wav"; + description = AudioClosest3d; + preload = true; +}; + +//SOUNDS ----- LIGHT ARMOR-------- +datablock AudioProfile(LFootLightSoftSound) +{ + filename = "fx/armor/light_LF_soft.wav"; + description = AudioClosest3d; + preload = true; +}; + +datablock AudioProfile(RFootLightSoftSound) +{ + filename = "fx/armor/light_RF_soft.wav"; + description = AudioClosest3d; + preload = true; +}; + +datablock AudioProfile(LFootLightHardSound) +{ + filename = "fx/armor/light_LF_hard.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(RFootLightHardSound) +{ + filename = "fx/armor/light_RF_hard.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(LFootLightMetalSound) +{ + filename = "fx/armor/light_LF_metal.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(RFootLightMetalSound) +{ + filename = "fx/armor/light_RF_metal.wav"; + description = AudioClose3d; + preload = true; +}; +datablock AudioProfile(LFootLightSnowSound) +{ + filename = "fx/armor/light_LF_snow.wav"; + description = AudioClosest3d; + preload = true; +}; + +datablock AudioProfile(RFootLightSnowSound) +{ + filename = "fx/armor/light_RF_snow.wav"; + description = AudioClosest3d; + preload = true; +}; + +datablock AudioProfile(LFootLightShallowSplashSound) +{ + filename = "fx/armor/light_LF_water.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(RFootLightShallowSplashSound) +{ + filename = "fx/armor/light_RF_water.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(LFootLightWadingSound) +{ + filename = "fx/armor/light_LF_wade.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(RFootLightWadingSound) +{ + filename = "fx/armor/light_RF_wade.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(LFootLightUnderwaterSound) +{ + filename = "fx/armor/light_LF_uw.wav"; + description = AudioClosest3d; + preload = true; +}; + +datablock AudioProfile(RFootLightUnderwaterSound) +{ + filename = "fx/armor/light_RF_uw.wav"; + description = AudioClosest3d; + preload = true; +}; + +datablock AudioProfile(LFootLightBubblesSound) +{ + filename = "fx/armor/light_LF_bubbles.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(RFootLightBubblesSound) +{ + filename = "fx/armor/light_RF_bubbles.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(ImpactLightSoftSound) +{ + filename = "fx/armor/light_land_soft.wav"; + description = AudioClose3d; + preload = true; + effect = ImpactSoftEffect; +}; + +datablock AudioProfile(ImpactLightHardSound) +{ + filename = "fx/armor/light_land_hard.wav"; + description = AudioClose3d; + preload = true; + effect = ImpactHardEffect; +}; + +datablock AudioProfile(ImpactLightMetalSound) +{ + filename = "fx/armor/light_land_metal.wav"; + description = AudioClose3d; + preload = true; + effect = ImpactMetalEffect; +}; + +datablock AudioProfile(ImpactLightSnowSound) +{ + filename = "fx/armor/light_land_snow.wav"; + description = AudioClosest3d; + preload = true; + effect = ImpactSnowEffect; +}; + +datablock AudioProfile(ImpactLightWaterEasySound) +{ + filename = "fx/armor/general_water_smallsplash2.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(ImpactLightWaterMediumSound) +{ + filename = "fx/armor/general_water_medsplash.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(ImpactLightWaterHardSound) +{ + filename = "fx/armor/general_water_bigsplash.wav"; + description = AudioDefault3d; + preload = true; +}; + +datablock AudioProfile(ExitingWaterLightSound) +{ + filename = "fx/armor/general_water_exit2.wav"; + description = AudioClose3d; + preload = true; +}; + +//SOUNDS ----- Medium ARMOR-------- +datablock AudioProfile(LFootMediumSoftSound) +{ + filename = "fx/armor/med_LF_soft.wav"; + description = AudioClosest3d; + preload = true; +}; + +datablock AudioProfile(RFootMediumSoftSound) +{ + filename = "fx/armor/med_RF_soft.wav"; + description = AudioClosest3d; + preload = true; +}; + +datablock AudioProfile(LFootMediumHardSound) +{ + filename = "fx/armor/med_LF_hard.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(RFootMediumHardSound) +{ + filename = "fx/armor/med_RF_hard.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(LFootMediumMetalSound) +{ + filename = "fx/armor/med_LF_metal.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(RFootMediumMetalSound) +{ + filename = "fx/armor/med_RF_metal.wav"; + description = AudioClose3d; + preload = true; +}; +datablock AudioProfile(LFootMediumSnowSound) +{ + filename = "fx/armor/med_LF_snow.wav"; + description = AudioClosest3d; + preload = true; +}; + +datablock AudioProfile(RFootMediumSnowSound) +{ + filename = "fx/armor/med_RF_snow.wav"; + description = AudioClosest3d; + preload = true; +}; + +datablock AudioProfile(LFootMediumShallowSplashSound) +{ + filename = "fx/armor/med_LF_water.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(RFootMediumShallowSplashSound) +{ + filename = "fx/armor/med_RF_water.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(LFootMediumWadingSound) +{ + filename = "fx/armor/med_LF_uw.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(RFootMediumWadingSound) +{ + filename = "fx/armor/med_RF_uw.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(LFootMediumUnderwaterSound) +{ + filename = "fx/armor/med_LF_uw.wav"; + description = AudioClosest3d; + preload = true; +}; + +datablock AudioProfile(RFootMediumUnderwaterSound) +{ + filename = "fx/armor/med_RF_uw.wav"; + description = AudioClosest3d; + preload = true; +}; + +datablock AudioProfile(LFootMediumBubblesSound) +{ + filename = "fx/armor/light_LF_bubbles.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(RFootMediumBubblesSound) +{ + filename = "fx/armor/light_RF_bubbles.wav"; + description = AudioClose3d; + preload = true; +}; +datablock AudioProfile(ImpactMediumSoftSound) +{ + filename = "fx/armor/med_land_soft.wav"; + description = AudioClosest3d; + preload = true; + effect = ImpactSoftEffect; +}; + +datablock AudioProfile(ImpactMediumHardSound) +{ + filename = "fx/armor/med_land_hard.wav"; + description = AudioClose3d; + preload = true; + effect = ImpactHardEffect; +}; + +datablock AudioProfile(ImpactMediumMetalSound) +{ + filename = "fx/armor/med_land_metal.wav"; + description = AudioClose3d; + preload = true; + effect = ImpactMetalEffect; +}; + +datablock AudioProfile(ImpactMediumSnowSound) +{ + filename = "fx/armor/med_land_snow.wav"; + description = AudioClosest3d; + preload = true; + effect = ImpactSnowEffect; +}; + +datablock AudioProfile(ImpactMediumWaterEasySound) +{ + filename = "fx/armor/general_water_smallsplash.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(ImpactMediumWaterMediumSound) +{ + filename = "fx/armor/general_water_medsplash.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(ImpactMediumWaterHardSound) +{ + filename = "fx/armor/general_water_bigsplash.wav"; + description = AudioDefault3d; + preload = true; +}; + +datablock AudioProfile(ExitingWaterMediumSound) +{ + filename = "fx/armor/general_water_exit.wav"; + description = AudioClose3d; + preload = true; +}; + +//SOUNDS ----- HEAVY ARMOR-------- +datablock AudioProfile(LFootHeavySoftSound) +{ + filename = "fx/armor/heavy_LF_soft.wav"; + description = AudioClosest3d; + preload = true; +}; + +datablock AudioProfile(RFootHeavySoftSound) +{ + filename = "fx/armor/heavy_RF_soft.wav"; + description = AudioClosest3d; + preload = true; +}; + +datablock AudioProfile(LFootHeavyHardSound) +{ + filename = "fx/armor/heavy_LF_hard.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(RFootHeavyHardSound) +{ + filename = "fx/armor/heavy_RF_hard.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(LFootHeavyMetalSound) +{ + filename = "fx/armor/heavy_LF_metal.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(RFootHeavyMetalSound) +{ + filename = "fx/armor/heavy_RF_metal.wav"; + description = AudioClose3d; + preload = true; +}; +datablock AudioProfile(LFootHeavySnowSound) +{ + filename = "fx/armor/heavy_LF_snow.wav"; + description = AudioClosest3d; + preload = true; +}; + +datablock AudioProfile(RFootHeavySnowSound) +{ + filename = "fx/armor/heavy_RF_snow.wav"; + description = AudioClosest3d; + preload = true; +}; + +datablock AudioProfile(LFootHeavyShallowSplashSound) +{ + filename = "fx/armor/heavy_LF_water.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(RFootHeavyShallowSplashSound) +{ + filename = "fx/armor/heavy_RF_water.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(LFootHeavyWadingSound) +{ + filename = "fx/armor/heavy_LF_uw.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(RFootHeavyWadingSound) +{ + filename = "fx/armor/heavy_RF_uw.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(LFootHeavyUnderwaterSound) +{ + filename = "fx/armor/heavy_LF_uw.wav"; + description = AudioClosest3d; + preload = true; +}; + +datablock AudioProfile(RFootHeavyUnderwaterSound) +{ + filename = "fx/armor/heavy_RF_uw.wav"; + description = AudioClosest3d; + preload = true; +}; + +datablock AudioProfile(LFootHeavyBubblesSound) +{ + filename = "fx/armor/light_LF_bubbles.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(RFootHeavyBubblesSound) +{ + filename = "fx/armor/light_RF_bubbles.wav"; + description = AudioClose3d; + preload = true; +}; +datablock AudioProfile(ImpactHeavySoftSound) +{ + filename = "fx/armor/heavy_land_soft.wav"; + description = AudioClose3d; + preload = true; + effect = ImpactSoftEffect; +}; + +datablock AudioProfile(ImpactHeavyHardSound) +{ + filename = "fx/armor/heavy_land_hard.wav"; + description = AudioClose3d; + preload = true; + effect = ImpactHardEffect; +}; + +datablock AudioProfile(ImpactHeavyMetalSound) +{ + filename = "fx/armor/heavy_land_metal.wav"; + description = AudioClose3d; + preload = true; + effect = ImpactMetalEffect; +}; + +datablock AudioProfile(ImpactHeavySnowSound) +{ + filename = "fx/armor/heavy_land_snow.wav"; + description = AudioClosest3d; + preload = true; + effect = ImpactSnowEffect; +}; + +datablock AudioProfile(ImpactHeavyWaterEasySound) +{ + filename = "fx/armor/general_water_smallsplash.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(ImpactHeavyWaterMediumSound) +{ + filename = "fx/armor/general_water_medsplash.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(ImpactHeavyWaterHardSound) +{ + filename = "fx/armor/general_water_bigsplash.wav"; + description = AudioDefault3d; + preload = true; +}; + +datablock AudioProfile(ExitingWaterHeavySound) +{ + filename = "fx/armor/general_water_exit2.wav"; + description = AudioClose3d; + preload = true; +}; + +//---------------------------------------------------------------------------- +// Splash +//---------------------------------------------------------------------------- + +datablock ParticleData(PlayerSplashMist) +{ + 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(PlayerSplashMistEmitter) +{ + ejectionPeriodMS = 5; + periodVarianceMS = 0; + ejectionVelocity = 3.0; + velocityVariance = 2.0; + ejectionOffset = 0.0; + thetaMin = 85; + thetaMax = 85; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + lifetimeMS = 250; + particles = "PlayerSplashMist"; +}; + + +datablock ParticleData(PlayerBubbleParticle) +{ + dragCoefficient = 0.0; + gravityCoefficient = -0.50; + inheritedVelFactor = 0.0; + constantAcceleration = 0.0; + lifetimeMS = 400; + lifetimeVarianceMS = 100; + useInvAlpha = false; + textureName = "special/bubbles"; + 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.1; + sizes[1] = 0.3; + sizes[2] = 0.3; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; +}; + +datablock ParticleEmitterData(PlayerBubbleEmitter) +{ + ejectionPeriodMS = 1; + periodVarianceMS = 0; + ejectionVelocity = 2.0; + ejectionOffset = 0.5; + velocityVariance = 0.5; + thetaMin = 0; + thetaMax = 80; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + particles = "PlayerBubbleParticle"; +}; + +datablock ParticleData(PlayerFoamParticle) +{ + 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 0.20"; + colors[1] = "0.7 0.8 1.0 0.20"; + colors[2] = "0.7 0.8 1.0 0.00"; + sizes[0] = 0.2; + sizes[1] = 0.4; + sizes[2] = 1.6; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; +}; + +datablock ParticleEmitterData(PlayerFoamEmitter) +{ + ejectionPeriodMS = 10; + periodVarianceMS = 0; + ejectionVelocity = 3.0; + velocityVariance = 1.0; + ejectionOffset = 0.0; + thetaMin = 85; + thetaMax = 85; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + particles = "PlayerFoamParticle"; +}; + + +datablock ParticleData( PlayerFoamDropletsParticle ) +{ + 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.8; + sizes[1] = 0.3; + sizes[2] = 0.0; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; +}; + +datablock ParticleEmitterData( PlayerFoamDropletsEmitter ) +{ + ejectionPeriodMS = 7; + periodVarianceMS = 0; + ejectionVelocity = 2; + velocityVariance = 1.0; + ejectionOffset = 0.0; + thetaMin = 60; + thetaMax = 80; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + orientParticles = true; + particles = "PlayerFoamDropletsParticle"; +}; + + + +datablock ParticleData( PlayerSplashParticle ) +{ + 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( PlayerSplashEmitter ) +{ + ejectionPeriodMS = 1; + periodVarianceMS = 0; + ejectionVelocity = 3; + velocityVariance = 1.0; + ejectionOffset = 0.0; + thetaMin = 60; + thetaMax = 80; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + orientParticles = true; + lifetimeMS = 100; + particles = "PlayerSplashParticle"; +}; + +datablock SplashData(PlayerSplash) +{ + numSegments = 15; + ejectionFreq = 15; + ejectionAngle = 40; + ringLifetime = 0.5; + lifetimeMS = 300; + velocity = 4.0; + startRadius = 0.0; + acceleration = -3.0; + texWrap = 5.0; + + texture = "special/water2"; + + emitter[0] = PlayerSplashEmitter; + emitter[1] = PlayerSplashMistEmitter; + + colors[0] = "0.7 0.8 1.0 0.0"; + colors[1] = "0.7 0.8 1.0 0.3"; + colors[2] = "0.7 0.8 1.0 0.7"; + 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; +}; + +//---------------------------------------------------------------------------- +// Jet data +//---------------------------------------------------------------------------- +datablock ParticleData(HumanArmorJetParticle) +{ + dragCoefficient = 1.5; //Was 0.0, original game shiped as 1.5 + gravityCoefficient = 0; + inheritedVelFactor = 0.2; + constantAcceleration = 0.0; + lifetimeMS = 100; //Was a watered down 100, Original game was 150 + lifetimeVarianceMS = 0; + textureName = "particleTest"; + colors[0] = "0.32 0.47 0.47 1.0"; + colors[1] = "0.32 0.47 0.47 0"; + sizes[0] = 0.40; + sizes[1] = 0.15; +}; + +datablock ParticleEmitterData(HumanArmorJetEmitter) +{ + ejectionPeriodMS = 3; + periodVarianceMS = 0; + ejectionVelocity = 3; + velocityVariance = 2.9; + ejectionOffset = 0.0; + thetaMin = 0; + thetaMax = 5; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + particles = "HumanArmorJetParticle"; +}; + +datablock JetEffectData(HumanArmorJetEffect) +{ + texture = "special/jetExhaust02"; + coolColor = "0.0 0.0 1.0 1.0"; + hotColor = "0.2 0.4 0.7 1.0"; + activateTime = 0.2; + deactivateTime = 0.05; + length = 0.75; + width = 0.2; + speed = -15; + stretch = 2.0; + yOffset = 0.2; +}; + +datablock JetEffectData(HumanMediumArmorJetEffect) +{ + texture = "special/jetExhaust02"; + coolColor = "0.0 0.0 1.0 1.0"; + hotColor = "0.2 0.4 0.7 1.0"; + activateTime = 0.2; + deactivateTime = 0.05; + length = 0.75; + width = 0.2; + speed = -15; + stretch = 2.0; + yOffset = 0.4; +}; + +datablock JetEffectData(HumanLightFemaleArmorJetEffect) +{ + texture = "special/jetExhaust02"; + coolColor = "0.0 0.0 1.0 1.0"; + hotColor = "0.2 0.4 0.7 1.0"; + activateTime = 0.2; + deactivateTime = 0.05; + length = 0.75; + width = 0.2; + speed = -15; + stretch = 2.0; + yOffset = 0.2; +}; + +datablock JetEffectData(BiodermArmorJetEffect) +{ + texture = "special/jetExhaust02"; + coolColor = "0.0 0.0 1.0 1.0"; + hotColor = "0.8 0.6 0.2 1.0"; + activateTime = 0.2; + deactivateTime = 0.05; + length = 0.75; + width = 0.2; + speed = -15; + stretch = 2.0; + yOffset = 0.0; +}; + +//---------------------------------------------------------------------------- +// Foot puffs +//---------------------------------------------------------------------------- +datablock ParticleData(LightPuff) +{ + dragCoefficient = 2.0; + gravityCoefficient = -0.01; + inheritedVelFactor = 0.0; + constantAcceleration = 0.0; + lifetimeMS = 500; + lifetimeVarianceMS = 100; + useInvAlpha = true; + spinRandomMin = -35.0; + spinRandomMax = 35.0; + textureName = "particleTest"; + colors[0] = "0.46 0.36 0.26 0.4"; + colors[1] = "0.46 0.46 0.36 0.0"; + sizes[0] = 0.4; + sizes[1] = 1.0; +}; + +datablock ParticleEmitterData(LightPuffEmitter) +{ + ejectionPeriodMS = 35; + periodVarianceMS = 10; + ejectionVelocity = 0.1; + velocityVariance = 0.05; + ejectionOffset = 0.0; + thetaMin = 5; + thetaMax = 20; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + useEmitterColors = true; + particles = "LightPuff"; +}; + +//---------------------------------------------------------------------------- +// Liftoff dust +//---------------------------------------------------------------------------- +datablock ParticleData(LiftoffDust) +{ + dragCoefficient = 1.0; + gravityCoefficient = -0.01; + inheritedVelFactor = 0.0; + constantAcceleration = 0.0; + lifetimeMS = 1000; + lifetimeVarianceMS = 100; + useInvAlpha = true; + spinRandomMin = -90.0; + spinRandomMax = 500.0; + textureName = "particleTest"; + colors[0] = "0.46 0.36 0.26 0.0"; + colors[1] = "0.46 0.46 0.36 0.4"; + colors[2] = "0.46 0.46 0.36 0.0"; + sizes[0] = 0.2; + sizes[1] = 0.6; + sizes[2] = 1.0; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; +}; + +datablock ParticleEmitterData(LiftoffDustEmitter) +{ + ejectionPeriodMS = 5; + periodVarianceMS = 0; + ejectionVelocity = 2.0; + velocityVariance = 0.0; + ejectionOffset = 0.0; + thetaMin = 90; + thetaMax = 90; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + useEmitterColors = true; + particles = "LiftoffDust"; +}; + +//---------------------------------------------------------------------------- + +datablock ParticleData(BiodermArmorJetParticle) : HumanArmorJetParticle +{ + colors[0] = "0.50 0.48 0.36 1.0"; + colors[1] = "0.50 0.48 0.36 0"; +}; + +datablock ParticleEmitterData(BiodermArmorJetEmitter) : HumanArmorJetEmitter +{ + particles = "BiodermArmorJetParticle"; +}; + + +//---------------------------------------------------------------------------- +datablock DecalData(LightMaleFootprint) +{ + sizeX = 0.125; + sizeY = 0.25; + textureName = "special/footprints/L_male"; +}; + +datablock DebrisData( PlayerDebris ) +{ + explodeOnMaxBounce = false; + + elasticity = 0.35; + friction = 0.5; + + lifetime = 4.0; + lifetimeVariance = 0.0; + + minSpinSpeed = 60; + maxSpinSpeed = 600; + + numBounces = 5; + bounceVariance = 0; + + staticOnMaxBounce = true; + gravModifier = 1.0; + + useRadiusMass = true; + baseRadius = 1; + + velocity = 18.0; + velocityVariance = 12.0; +}; + +datablock PlayerData(LightMaleHumanArmor) : LightPlayerDamageProfile +{ + emap = true; + + className = Armor; + shapeFile = "light_male.dts"; + cameraMaxDist = 3; + computeCRC = true; + + canObserve = true; + cmdCategory = "Clients"; + cmdIcon = CMDPlayerIcon; + cmdMiniIconName = "commander/MiniIcons/com_player_grey"; + + hudImageNameFriendly[0] = "gui/hud_playertriangle"; + hudImageNameEnemy[0] = "gui/hud_playertriangle_enemy"; + hudRenderModulated[0] = true; + + hudImageNameFriendly[1] = "commander/MiniIcons/com_flag_grey"; + hudImageNameEnemy[1] = "commander/MiniIcons/com_flag_grey"; + hudRenderModulated[1] = true; + hudRenderAlways[1] = true; + hudRenderCenter[1] = true; + hudRenderDistance[1] = true; + + hudImageNameFriendly[2] = "commander/MiniIcons/com_flag_grey"; + hudImageNameEnemy[2] = "commander/MiniIcons/com_flag_grey"; + hudRenderModulated[2] = true; + hudRenderAlways[2] = true; + hudRenderCenter[2] = true; + hudRenderDistance[2] = true; + + cameraDefaultFov = 90.0; + cameraMinFov = 5.0; + cameraMaxFov = 120.0; + + debrisShapeName = "debris_player.dts"; + debris = playerDebris; + + aiAvoidThis = true; + + minLookAngle = -1.5; + maxLookAngle = 1.5; + maxFreelookAngle = 3.0; + + mass = 90; + drag = 0.275; + maxdrag = 0.4; + density = 10; + maxDamage = 0.66; + maxEnergy = 60; + repairRate = 0.0033; + energyPerDamagePoint = 75.0; // shield energy required to block one point of damage + + rechargeRate = 0.256; + jetForce = 26.21 * 90; + underwaterJetForce = 26.21 * 90 * 1.5; + underwaterVertJetFactor = 1.5; + jetEnergyDrain = 0.8; + underwaterJetEnergyDrain = 0.6; + minJetEnergy = 1; + maxJetHorizontalPercentage = 0.8; + + runForce = 55.20 * 90; + runEnergyDrain = 0; + minRunEnergy = 0; + maxForwardSpeed = 15; + maxBackwardSpeed = 13; + maxSideSpeed = 13; + + maxUnderwaterForwardSpeed = 11; + maxUnderwaterBackwardSpeed = 10; + maxUnderwaterSideSpeed = 10; + + + jumpForce = 8.3 * 90; + jumpEnergyDrain = 0; + minJumpEnergy = 0; + jumpDelay = 0; + + + recoverDelay = 9; + recoverRunForceScale = 1.2; + + minImpactSpeed = 45; + speedDamageScale = 0.004; + + jetSound = ArmorJetSound; + wetJetSound = ArmorJetSound; + jetEmitter = HumanArmorJetEmitter; + jetEffect = HumanArmorJetEffect; + + boundingBox = "1.2 1.2 2.3"; + pickupRadius = 0.75; + + // damage location details + boxNormalHeadPercentage = 0.83; + boxNormalTorsoPercentage = 0.49; + boxHeadLeftPercentage = 0; + boxHeadRightPercentage = 1; + boxHeadBackPercentage = 0; + boxHeadFrontPercentage = 1; + + //Foot Prints + decalData = LightMaleFootprint; + decalOffset = 0.25; + + footPuffEmitter = LightPuffEmitter; + footPuffNumParts = 15; + footPuffRadius = 0.25; + + dustEmitter = LiftoffDustEmitter; + + splash = PlayerSplash; + splashVelocity = 4.0; + splashAngle = 67.0; + splashFreqMod = 300.0; + splashVelEpsilon = 0.60; + bubbleEmitTime = 0.4; + splashEmitter[0] = PlayerFoamDropletsEmitter; + splashEmitter[1] = PlayerFoamEmitter; + splashEmitter[2] = PlayerBubbleEmitter; + mediumSplashSoundVelocity = 10.0; + hardSplashSoundVelocity = 20.0; + exitSplashSoundVelocity = 5.0; + + // Controls over slope of runnable/jumpable surfaces + runSurfaceAngle = 70; + jumpSurfaceAngle = 80; + + minJumpSpeed = 20; + maxJumpSpeed = 30; + + horizMaxSpeed = 68; + horizResistSpeed = 33; + horizResistFactor = 0.35; + maxJetForwardSpeed = 30; + + upMaxSpeed = 80; + upResistSpeed = 25; + upResistFactor = 0.3; + + // heat inc'ers and dec'ers + heatDecayPerSec = 1.0 / 4.0; // takes 4 seconds to clear heat sig. + heatIncreasePerSec = 1.0 / 3.0; // takes 3.0 seconds of constant jet to get full heat sig. + + footstepSplashHeight = 0.35; + //Footstep Sounds + LFootSoftSound = LFootLightSoftSound; + RFootSoftSound = RFootLightSoftSound; + LFootHardSound = LFootLightHardSound; + RFootHardSound = RFootLightHardSound; + LFootMetalSound = LFootLightMetalSound; + RFootMetalSound = RFootLightMetalSound; + LFootSnowSound = LFootLightSnowSound; + RFootSnowSound = RFootLightSnowSound; + LFootShallowSound = LFootLightShallowSplashSound; + RFootShallowSound = RFootLightShallowSplashSound; + LFootWadingSound = LFootLightWadingSound; + RFootWadingSound = RFootLightWadingSound; + LFootUnderwaterSound = LFootLightUnderwaterSound; + RFootUnderwaterSound = RFootLightUnderwaterSound; + LFootBubblesSound = LFootLightBubblesSound; + RFootBubblesSound = RFootLightBubblesSound; + movingBubblesSound = ArmorMoveBubblesSound; + waterBreathSound = WaterBreathMaleSound; + + impactSoftSound = ImpactLightSoftSound; + impactHardSound = ImpactLightHardSound; + impactMetalSound = ImpactLightMetalSound; + impactSnowSound = ImpactLightSnowSound; + + skiSoftSound = SkiAllSoftSound; + skiHardSound = SkiAllHardSound; + skiMetalSound = SkiAllMetalSound; + skiSnowSound = SkiAllSnowSound; + + impactWaterEasy = ImpactLightWaterEasySound; + impactWaterMedium = ImpactLightWaterMediumSound; + impactWaterHard = ImpactLightWaterHardSound; + + groundImpactMinSpeed = 10.0; + groundImpactShakeFreq = "4.0 4.0 4.0"; + groundImpactShakeAmp = "1.0 1.0 1.0"; + groundImpactShakeDuration = 0.8; + groundImpactShakeFalloff = 10.0; + + exitingWater = ExitingWaterLightSound; + + maxWeapons = 3; // Max number of different weapons the player can have + maxGrenades = 1; // Max number of different grenades the player can have + maxMines = 1; // Max number of different mines the player can have + + // Inventory restrictions + max[RepairKit] = 1; + max[Mine] = 3; + max[Grenade] = 5; + max[Blaster] = 1; + max[Plasma] = 1; + max[PlasmaAmmo] = 20; + max[Disc] = 1; + max[DiscAmmo] = 15; + max[SniperRifle] = 1; + max[GrenadeLauncher] = 1; + max[GrenadeLauncherAmmo] = 10; + max[Mortar] = 0; + max[MortarAmmo] = 0; + max[MissileLauncher] = 0; + max[MissileLauncherAmmo] = 0; + max[Chaingun] = 1; + max[ChaingunAmmo] = 100; + max[RepairGun] = 1; + max[CloakingPack] = 1; + max[SensorJammerPack] = 1; + max[EnergyPack] = 1; + max[RepairPack] = 1; + max[ShieldPack] = 1; + max[AmmoPack] = 1; + max[SatchelCharge] = 1; + max[MortarBarrelPack] = 0; + max[MissileBarrelPack] = 0; + max[AABarrelPack] = 0; + max[PlasmaBarrelPack] = 0; + max[ELFBarrelPack] = 0; + max[InventoryDeployable] = 0; + max[MotionSensorDeployable] = 1; + max[PulseSensorDeployable] = 1; + max[TurretOutdoorDeployable] = 0; + max[TurretIndoorDeployable] = 0; + max[FlashGrenade] = 5; + max[ConcussionGrenade] = 5; + max[FlareGrenade] = 5; + max[TargetingLaser] = 1; + max[ELFGun] = 1; + max[ShockLance] = 1; + max[CameraGrenade] = 2; + max[Beacon] = 3; + //Guns + max[ConstructionTool] = 1; + max[NerfGun] = 1; + max[NerfBallLauncher] = 1; + max[NerfBallLauncherAmmo] = 25; + max[SuperChaingun] = 0; + max[SuperChaingunAmmo] = 0; + max[MergeTool] =1; + //Building parts + max[spineDeployable] = 1; + max[mspineDeployable] = 0; + max[wWallDeployable] = 1; + max[floorDeployable] = 0; + max[WallDeployable] = 0; + //Turrets + max[TurretLaserDeployable] = 1; + max[TurretMissileRackDeployable]= 0; + max[DiscTurretDeployable] = 0; + //Largepacks + max[EnergizerDeployable] = 0; + max[TreeDeployable] = 0; + max[CrateDeployable] = 0; + max[DecorationDeployable] = 0; + max[LogoProjectorDeployable] = 0; + max[LightDeployable] = 1; + max[TripwireDeployable] = 1; + max[TelePadPack] = 0; + max[TurretBasePack] = 0; + max[LargeInventoryDeployable] = 0; + max[GeneratorDeployable] = 0; + max[SolarPanelDeployable] = 0; + max[SwitchDeployable] = 0; + max[MediumSensorDeployable] = 0; + max[LargeSensorDeployable] = 0; + //Misc + max[JumpadDeployable] = 0; + max[EscapePodDeployable] = 0; + max[ForceFieldDeployable] = 0; + max[GravityFieldDeployable] = 0; + + observeParameters = "0.5 4.5 4.5"; + shieldEffectScale = "0.7 0.7 1.0"; +}; + + +//---------------------------------------------------------------------------- + +datablock DecalData(MediumMaleFootprint) +{ + sizeX = 0.125; + sizeY = 0.25; + textureName = "special/footprints/M_male"; +}; + +datablock PlayerData(MediumMaleHumanArmor) : MediumPlayerDamageProfile +{ + emap = true; + + className = Armor; + shapeFile = "medium_male.dts"; + cameraMaxDist = 3; + computeCRC = true; + + debrisShapeName = "debris_player.dts"; + debris = playerDebris; + + canObserve = true; + cmdCategory = "Clients"; + cmdIcon = CMDPlayerIcon; + cmdMiniIconName = "commander/MiniIcons/com_player_grey"; + + hudImageNameFriendly[0] = "gui/hud_playertriangle"; + hudImageNameEnemy[0] = "gui/hud_playertriangle_enemy"; + hudRenderModulated[0] = true; + + hudImageNameFriendly[1] = "commander/MiniIcons/com_flag_grey"; + hudImageNameEnemy[1] = "commander/MiniIcons/com_flag_grey"; + hudRenderModulated[1] = true; + hudRenderAlways[1] = true; + hudRenderCenter[1] = true; + hudRenderDistance[1] = true; + + hudImageNameFriendly[2] = "commander/MiniIcons/com_flag_grey"; + hudImageNameEnemy[2] = "commander/MiniIcons/com_flag_grey"; + hudRenderModulated[2] = true; + hudRenderAlways[2] = true; + hudRenderCenter[2] = true; + hudRenderDistance[2] = true; + + // z0dd - ZOD, 10/06/02. Was missing these parameters. + cameraDefaultFov = 90.0; + cameraMinFov = 5.0; + cameraMaxFov = 120.0; + + aiAvoidThis = true; + + minLookAngle = -1.5; + maxLookAngle = 1.5; + maxFreelookAngle = 3.0; + + mass = 130; + drag = 0.3; + maxdrag = 0.5; + density = 10; + maxDamage = 1.1; + maxEnergy = 80; + repairRate = 0.0033; + energyPerDamagePoint = 75.0; // shield energy required to block one point of damage + + rechargeRate = 0.256; + jetForce = 25.22 * 130; + underwaterJetForce = 25.22 * 130 * 1.5; + underwaterVertJetFactor = 1.5; + jetEnergyDrain = 1.0; + underwaterJetEnergyDrain = 0.6; + minJetEnergy = 1; + maxJetHorizontalPercentage = 0.8; + + runForce = 46 * 130; + runEnergyDrain = 0; + minRunEnergy = 0; + maxForwardSpeed = 12; + maxBackwardSpeed = 10; + maxSideSpeed = 10; + + maxUnderwaterForwardSpeed = 8.5; + maxUnderwaterBackwardSpeed = 7.5; + maxUnderwaterSideSpeed = 7.5; + + recoverDelay = 9; + recoverRunForceScale = 1.2; + + // heat inc'ers and dec'ers + heatDecayPerSec = 1.0 / 4.0; // takes 4 seconds to clear heat sig. + heatIncreasePerSec = 1.0 / 3.0; // takes 3.0 seconds of constant jet to get full heat sig. + + jumpForce = 8.3 * 130; + jumpEnergyDrain = 0; + minJumpEnergy = 0; + jumpSurfaceAngle = 75; + jumpDelay = 0; + + // Controls over slope of runnable/jumpable surfaces + runSurfaceAngle = 70; + jumpSurfaceAngle = 80; + + minJumpSpeed = 15; + maxJumpSpeed = 25; + + horizMaxSpeed = 60; + horizResistSpeed = 28; + horizResistFactor = 0.32; + maxJetForwardSpeed = 22; + + upMaxSpeed = 70; + upResistSpeed = 30; + upResistFactor = 0.23; + + minImpactSpeed = 45; + speedDamageScale = 0.004; + + jetSound = ArmorJetSound; + wetJetSound = ArmorWetJetSound; + + jetEmitter = HumanArmorJetEmitter; + jetEffect = HumanMediumArmorJetEffect; + + boundingBox = "1.45 1.45 2.4"; + pickupRadius = 0.75; + + // damage location details + boxNormalHeadPercentage = 0.83; + boxNormalTorsoPercentage = 0.49; + boxHeadLeftPercentage = 0; + boxHeadRightPercentage = 1; + boxHeadBackPercentage = 0; + boxHeadFrontPercentage = 1; + + //Foot Prints + decalData = MediumMaleFootprint; + decalOffset = 0.35; + + footPuffEmitter = LightPuffEmitter; + footPuffNumParts = 15; + footPuffRadius = 0.25; + + dustEmitter = LiftoffDustEmitter; + + splash = PlayerSplash; + splashVelocity = 4.0; + splashAngle = 67.0; + splashFreqMod = 300.0; + splashVelEpsilon = 0.60; + bubbleEmitTime = 0.4; + splashEmitter[0] = PlayerFoamDropletsEmitter; + splashEmitter[1] = PlayerFoamEmitter; + splashEmitter[2] = PlayerBubbleEmitter; + mediumSplashSoundVelocity = 10.0; + hardSplashSoundVelocity = 20.0; + exitSplashSoundVelocity = 5.0; + + footstepSplashHeight = 0.35; + //Footstep Sounds + LFootSoftSound = LFootMediumSoftSound; + RFootSoftSound = RFootMediumSoftSound; + LFootHardSound = LFootMediumHardSound; + RFootHardSound = RFootMediumHardSound; + LFootMetalSound = LFootMediumMetalSound; + RFootMetalSound = RFootMediumMetalSound; + LFootSnowSound = LFootMediumSnowSound; + RFootSnowSound = RFootMediumSnowSound; + LFootShallowSound = LFootMediumShallowSplashSound; + RFootShallowSound = RFootMediumShallowSplashSound; + LFootWadingSound = LFootMediumWadingSound; + RFootWadingSound = RFootMediumWadingSound; + LFootUnderwaterSound = LFootMediumUnderwaterSound; + RFootUnderwaterSound = RFootMediumUnderwaterSound; + LFootBubblesSound = LFootMediumBubblesSound; + RFootBubblesSound = RFootMediumBubblesSound; + movingBubblesSound = ArmorMoveBubblesSound; + waterBreathSound = WaterBreathMaleSound; + + impactSoftSound = ImpactMediumSoftSound; + impactHardSound = ImpactMediumHardSound; + impactMetalSound = ImpactMediumMetalSound; + impactSnowSound = ImpactMediumSnowSound; + + skiSoftSound = SkiAllSoftSound; + skiHardSound = SkiAllHardSound; + skiMetalSound = SkiAllMetalSound; + skiSnowSound = SkiAllSnowSound; + + impactWaterEasy = ImpactMediumWaterEasySound; + impactWaterMedium = ImpactMediumWaterMediumSound; + impactWaterHard = ImpactMediumWaterHardSound; + + groundImpactMinSpeed = 10.0; + groundImpactShakeFreq = "4.0 4.0 4.0"; + groundImpactShakeAmp = "1.0 1.0 1.0"; + groundImpactShakeDuration = 0.8; + groundImpactShakeFalloff = 10.0; + + exitingWater = ExitingWaterMediumSound; + + maxWeapons = 4; // Max number of different weapons the player can have + maxGrenades = 1; // Max number of different grenades the player can have + maxMines = 1; // Max number of different mines the player can have + + // Inventory restrictions + max[RepairKit] = 1; + max[Mine] = 3; + max[Grenade] = 6; + max[Blaster] = 1; + max[Plasma] = 1; + max[PlasmaAmmo] = 40; + max[Disc] = 1; + max[DiscAmmo] = 15; + max[SniperRifle] = 0; + max[GrenadeLauncher] = 1; + max[GrenadeLauncherAmmo] = 12; + max[Mortar] = 0; + max[MortarAmmo] = 0; + max[MissileLauncher] = 1; + max[MissileLauncherAmmo] = 4; + max[Chaingun] = 1; + max[ChaingunAmmo] = 150; + max[RepairGun] = 1; + max[CloakingPack] = 0; + max[SensorJammerPack] = 1; + max[EnergyPack] = 1; + max[RepairPack] = 1; + max[ShieldPack] = 1; + max[AmmoPack] = 1; + max[SatchelCharge] = 1; + max[MortarBarrelPack] = 1; + max[MissileBarrelPack] = 1; + max[AABarrelPack] = 1; + max[PlasmaBarrelPack] = 1; + max[ELFBarrelPack] = 1; + max[InventoryDeployable] = 1; + max[MotionSensorDeployable] = 1; + max[PulseSensorDeployable] = 1; + max[TurretOutdoorDeployable] = 1; + max[TurretIndoorDeployable] = 1; + max[FlashGrenade] = 6; + max[ConcussionGrenade] = 6; + max[FlareGrenade] = 6; + max[TargetingLaser] = 1; + max[ELFGun] = 1; + max[ShockLance] = 1; + max[CameraGrenade] = 3; + max[Beacon] = 3; + //Guns + max[ConstructionTool] = 1; + max[NerfGun] = 1; + max[NerfBallLauncher] = 1; + max[NerfBallLauncherAmmo] = 25; + max[SuperChaingun] = 0; + max[SuperChaingunAmmo] = 0; + max[MergeTool] =1; + //Building parts + max[spineDeployable] = 1; + max[mspineDeployable] = 1; + max[wWallDeployable] = 1; + max[floorDeployable] = 1; + max[WallDeployable] = 1; + //Turrets + max[TurretLaserDeployable] = 1; + max[TurretMissileRackDeployable]= 1; + max[DiscTurretDeployable] = 0; + //Largepacks + max[EnergizerDeployable] = 0; + max[TreeDeployable] = 1; + max[CrateDeployable] = 1; + max[DecorationDeployable] = 1; + max[LogoProjectorDeployable] = 1; + max[LightDeployable] = 1; + max[TripwireDeployable] = 1; + max[TelePadPack] = 1; + max[TurretBasePack] = 0; + max[LargeInventoryDeployable] = 0; + max[GeneratorDeployable] = 0; + max[SolarPanelDeployable] = 1; + max[SwitchDeployable] = 1; + max[MediumSensorDeployable] = 1; + max[LargeSensorDeployable] = 0; + //Misc + max[JumpadDeployable] = 1; + max[EscapePodDeployable] = 0; + max[ForceFieldDeployable] = 1; + max[GravityFieldDeployable] = 1; + + observeParameters = "0.5 4.5 4.5"; + shieldEffectScale = "0.7 0.7 1.0"; +}; + + +//---------------------------------------------------------------------------- +datablock DecalData(HeavyMaleFootprint) +{ + sizeX = 0.25; + sizeY = 0.5; + textureName = "special/footprints/H_male"; +}; + +datablock PlayerData(HeavyMaleHumanArmor) : HeavyPlayerDamageProfile +{ + emap = true; + + className = Armor; + shapeFile = "heavy_male.dts"; + cameraMaxDist = 3; + computeCRC = true; + + debrisShapeName = "debris_player.dts"; + debris = playerDebris; + + canObserve = true; + cmdCategory = "Clients"; + cmdIcon = CMDPlayerIcon; + cmdMiniIconName = "commander/MiniIcons/com_player_grey"; + + hudImageNameFriendly[0] = "gui/hud_playertriangle"; + hudImageNameEnemy[0] = "gui/hud_playertriangle_enemy"; + hudRenderModulated[0] = true; + + hudImageNameFriendly[1] = "commander/MiniIcons/com_flag_grey"; + hudImageNameEnemy[1] = "commander/MiniIcons/com_flag_grey"; + hudRenderModulated[1] = true; + hudRenderAlways[1] = true; + hudRenderCenter[1] = true; + hudRenderDistance[1] = true; + + hudImageNameFriendly[2] = "commander/MiniIcons/com_flag_grey"; + hudImageNameEnemy[2] = "commander/MiniIcons/com_flag_grey"; + hudRenderModulated[2] = true; + hudRenderAlways[2] = true; + hudRenderCenter[2] = true; + hudRenderDistance[2] = true; + + // z0dd - ZOD, 10/06/02. Was missing these parameters. + cameraDefaultFov = 90.0; + cameraMinFov = 5.0; + cameraMaxFov = 120.0; + + aiAvoidThis = true; + + minLookAngle = -1.5; + maxLookAngle = 1.5; + maxFreelookAngle = 3.0; + + mass = 180; + drag = 0.33; + maxdrag = 0.6; + density = 10; + maxDamage = 1.32; + maxEnergy = 110; + repairRate = 0.0033; + energyPerDamagePoint = 75.0; // shield energy required to block one point of damage + + rechargeRate = 0.256; + jetForce = 22.47 * 180; + underwaterJetForce = 22.47 * 180 * 1.5; + underwaterVertJetFactor = 1.5; + jetEnergyDrain = 1.1; + underwaterJetEnergyDrain = 0.65; + minJetEnergy = 1; + maxJetHorizontalPercentage = 0.8; + + runForce = 40.25 * 180; + runEnergyDrain = 0; + minRunEnergy = 0; + maxForwardSpeed = 7; + maxBackwardSpeed = 5; + maxSideSpeed = 5; + + maxUnderwaterForwardSpeed = 4.5; + maxUnderwaterBackwardSpeed = 3; + maxUnderwaterSideSpeed = 3; + + recoverDelay = 9; + recoverRunForceScale = 1.2; + + jumpForce = 8.3 * 180; + jumpEnergyDrain = 0; + minJumpEnergy = 0; + jumpDelay = 0; + + // heat inc'ers and dec'ers + heatDecayPerSec = 1.0 / 4.0; // takes 4 seconds to clear heat sig. + heatIncreasePerSec = 1.0 / 3.0; // takes 3.0 seconds of constant jet to get full heat sig. + + // Controls over slope of runnable/jumpable surfaces + runSurfaceAngle = 70; + jumpSurfaceAngle = 75; + + minJumpSpeed = 20; + maxJumpSpeed = 30; + + horizMaxSpeed = 52; + horizResistSpeed = 23; + horizResistFactor = 0.29; + maxJetForwardSpeed = 16; + + upMaxSpeed = 60; + upResistSpeed = 35; + upResistFactor = 0.18; + + minImpactSpeed = 45; + speedDamageScale = 0.006; + + jetSound = ArmorJetSound; + wetJetSound = ArmorJetSound; + jetEmitter = HumanArmorJetEmitter; + + boundingBox = "1.63 1.63 2.6"; + pickupRadius = 0.75; + + // damage location details + boxNormalHeadPercentage = 0.83; + boxNormalTorsoPercentage = 0.49; + boxHeadLeftPercentage = 0; + boxHeadRightPercentage = 1; + boxHeadBackPercentage = 0; + boxHeadFrontPercentage = 1; + + //Foot Prints + decalData = HeavyMaleFootprint; + decalOffset = 0.4; + + footPuffEmitter = LightPuffEmitter; + footPuffNumParts = 15; + footPuffRadius = 0.25; + + dustEmitter = LiftoffDustEmitter; + + splash = PlayerSplash; + splashVelocity = 4.0; + splashAngle = 67.0; + splashFreqMod = 300.0; + splashVelEpsilon = 0.60; + bubbleEmitTime = 0.4; + splashEmitter[0] = PlayerFoamDropletsEmitter; + splashEmitter[1] = PlayerFoamEmitter; + splashEmitter[2] = PlayerBubbleEmitter; + mediumSplashSoundVelocity = 10.0; + hardSplashSoundVelocity = 20.0; + exitSplashSoundVelocity = 5.0; + + footstepSplashHeight = 0.35; + //Footstep Sounds + LFootSoftSound = LFootHeavySoftSound; + RFootSoftSound = RFootHeavySoftSound; + LFootHardSound = LFootHeavyHardSound; + RFootHardSound = RFootHeavyHardSound; + LFootMetalSound = LFootHeavyMetalSound; + RFootMetalSound = RFootHeavyMetalSound; + LFootSnowSound = LFootHeavySnowSound; + RFootSnowSound = RFootHeavySnowSound; + LFootShallowSound = LFootHeavyShallowSplashSound; + RFootShallowSound = RFootHeavyShallowSplashSound; + LFootWadingSound = LFootHeavyWadingSound; + RFootWadingSound = RFootHeavyWadingSound; + LFootUnderwaterSound = LFootHeavyUnderwaterSound; + RFootUnderwaterSound = RFootHeavyUnderwaterSound; + LFootBubblesSound = LFootHeavyBubblesSound; + RFootBubblesSound = RFootHeavyBubblesSound; + movingBubblesSound = ArmorMoveBubblesSound; + waterBreathSound = WaterBreathMaleSound; + + impactSoftSound = ImpactHeavySoftSound; + impactHardSound = ImpactHeavyHardSound; + impactMetalSound = ImpactHeavyMetalSound; + impactSnowSound = ImpactHeavySnowSound; + + skiSoftSound = SkiAllSoftSound; + skiHardSound = SkiAllHardSound; + skiMetalSound = SkiAllMetalSound; + skiSnowSound = SkiAllSnowSound; + + impactWaterEasy = ImpactHeavyWaterEasySound; + impactWaterMedium = ImpactHeavyWaterMediumSound; + impactWaterHard = ImpactHeavyWaterHardSound; + + groundImpactMinSpeed = 10.0; + groundImpactShakeFreq = "4.0 4.0 4.0"; + groundImpactShakeAmp = "1.0 1.0 1.0"; + groundImpactShakeDuration = 0.8; + groundImpactShakeFalloff = 10.0; + + exitingWater = ExitingWaterHeavySound; + + maxWeapons = 5; // Max number of different weapons the player can have + maxGrenades = 1; // Max number of different grenades the player can have + maxMines = 1; // Max number of different mines the player can have + + // Inventory restrictions + max[RepairKit] = 1; + max[Mine] = 3; + max[Grenade] = 8; + max[Blaster] = 1; + max[Plasma] = 1; + max[PlasmaAmmo] = 50; + max[Disc] = 1; + max[DiscAmmo] = 15; + max[SniperRifle] = 0; + max[GrenadeLauncher] = 1; + max[GrenadeLauncherAmmo] = 15; + max[Mortar] = 1; + max[MortarAmmo] = 10; + max[MissileLauncher] = 1; + max[MissileLauncherAmmo] = 8; + max[Chaingun] = 1; + max[ChaingunAmmo] = 200; + max[RepairGun] = 1; + max[CloakingPack] = 0; + max[SensorJammerPack] = 1; + max[EnergyPack] = 1; + max[RepairPack] = 1; + max[ShieldPack] = 1; + max[AmmoPack] = 1; + max[SatchelCharge] = 1; + max[MortarBarrelPack] = 1; + max[MissileBarrelPack] = 1; + max[AABarrelPack] = 1; + max[PlasmaBarrelPack] = 1; + max[ELFBarrelPack] = 1; + max[InventoryDeployable] = 1; + max[MotionSensorDeployable] = 1; + max[PulseSensorDeployable] = 1; + max[TurretOutdoorDeployable] = 1; + max[TurretIndoorDeployable] = 1; + max[FlashGrenade] = 8; + max[ConcussionGrenade] = 8; + max[FlareGrenade] = 8; + max[TargetingLaser] = 1; + max[ELFGun] = 1; + max[ShockLance] = 1; + max[CameraGrenade] = 3; + max[Beacon] = 3; + //Guns + max[ConstructionTool] = 1; + max[NerfGun] = 1; + max[NerfBallLauncher] = 1; + max[NerfBallLauncherAmmo] = 25; + max[SuperChaingun] = 0; + max[SuperChaingunAmmo] = 0; + max[MergeTool] =1; + //Building parts + max[spineDeployable] = 1; + max[mspineDeployable] = 1; + max[wWallDeployable] = 1; + max[floorDeployable] = 1; + max[WallDeployable] = 1; + //Turrets + max[TurretLaserDeployable] = 1; + max[TurretMissileRackDeployable]= 1; + max[DiscTurretDeployable] = 0; + //Largepacks + max[EnergizerDeployable] = 1; + max[TreeDeployable] = 1; + max[CrateDeployable] = 1; + max[DecorationDeployable] = 1; + max[LogoProjectorDeployable] = 1; + max[LightDeployable] = 1; + max[TripwireDeployable] = 1; + max[TelePadPack] = 1; + max[TurretBasePack] = 1; + max[LargeInventoryDeployable] = 1; + max[GeneratorDeployable] = 1; + max[SolarPanelDeployable] = 1; + max[SwitchDeployable] = 1; + max[MediumSensorDeployable] = 1; + max[LargeSensorDeployable] = 1; + //Misc + max[JumpadDeployable] = 1; + max[EscapePodDeployable] = 1; + max[ForceFieldDeployable] = 1; + max[GravityFieldDeployable] = 1; + + observeParameters = "0.5 4.5 4.5"; + shieldEffectScale = "0.7 0.7 1.0"; +}; + + +//---------------------------------------------------------------------------- +datablock PlayerData(LightFemaleHumanArmor) : LightMaleHumanArmor +{ + shapeFile = "light_female.dts"; + waterBreathSound = WaterBreathFemaleSound; + jetEffect = HumanMediumArmorJetEffect; +}; + +//---------------------------------------------------------------------------- +datablock PlayerData(MediumFemaleHumanArmor) : MediumMaleHumanArmor +{ + shapeFile = "medium_female.dts"; + waterBreathSound = WaterBreathFemaleSound; + jetEffect = HumanArmorJetEffect; +}; + +//---------------------------------------------------------------------------- +datablock PlayerData(HeavyFemaleHumanArmor) : HeavyMaleHumanArmor +{ + shapeFile = "heavy_male.dts"; + waterBreathSound = WaterBreathFemaleSound; +}; + +//---------------------------------------------------------------------------- +datablock DecalData(LightBiodermFootprint) +{ + sizeX = 0.25; + sizeY = 0.25; + textureName = "special/footprints/L_bioderm"; +}; + +datablock PlayerData(LightMaleBiodermArmor) : LightMaleHumanArmor +{ + shapeFile = "bioderm_light.dts"; + jetEmitter = BiodermArmorJetEmitter; + jetEffect = BiodermArmorJetEffect; + + + debrisShapeName = "bio_player_debris.dts"; + + //Foot Prints + decalData = LightBiodermFootprint; + decalOffset = 0.3; + + waterBreathSound = WaterBreathBiodermSound; +}; + +//---------------------------------------------------------------------------- +datablock DecalData(MediumBiodermFootprint) +{ + sizeX = 0.25; + sizeY = 0.25; + textureName = "special/footprints/M_bioderm"; +}; + +datablock PlayerData(MediumMaleBiodermArmor) : MediumMaleHumanArmor +{ + shapeFile = "bioderm_medium.dts"; + jetEmitter = BiodermArmorJetEmitter; + jetEffect = BiodermArmorJetEffect; + + debrisShapeName = "bio_player_debris.dts"; + + //Foot Prints + decalData = MediumBiodermFootprint; + decalOffset = 0.35; + + waterBreathSound = WaterBreathBiodermSound; +}; + +//---------------------------------------------------------------------------- +datablock DecalData(HeavyBiodermFootprint) +{ + sizeX = 0.25; + sizeY = 0.5; + textureName = "special/footprints/H_bioderm"; +}; + +datablock PlayerData(HeavyMaleBiodermArmor) : HeavyMaleHumanArmor +{ + emap = false; + + shapeFile = "bioderm_heavy.dts"; + jetEmitter = BiodermArmorJetEmitter; + + debrisShapeName = "bio_player_debris.dts"; + + //Foot Prints + decalData = HeavyBiodermFootprint; + decalOffset = 0.4; + + waterBreathSound = WaterBreathBiodermSound; +}; + + + + + +// -------------------------------------------------------------------------- +// True Build Armors +// -------------------------------------------------------------------------- + +datablock PlayerData(PureMaleHumanArmor) : LightMaleHumanArmor +{ + jetForce = 26.21 * 120; // 26.21 * 90 + underwaterJetForce = 26.21 * 120 * 1.5; // 26.21 * 90 * 1.5 + + maxEnergy = 60; + jetEnergyDrain = 0.1; + underwaterJetEnergyDrain = 0.05; + rechargeRate = 0.256; + mass = 115; + + minImpactSpeed = 450; + speedDamageScale = 0.0004; + + maxWeapons = 3; // Max number of different weapons the player can have + maxGrenades = 1; // Max number of different grenades the player can have + maxMines = 0; // Max number of different mines the player can have + + // Inventory restrictions + max[RepairKit] = 0; + max[Mine] = 0; + max[Grenade] = 0; + max[Blaster] = 0; + max[Plasma] = 0; + max[PlasmaAmmo] = 0; + max[Disc] = 0; + max[DiscAmmo] = 0; + max[SniperRifle] = 0; + max[GrenadeLauncher] = 0; + max[GrenadeLauncherAmmo] = 0; + max[Mortar] = 0; + max[MortarAmmo] = 0; + max[MissileLauncher] = 0; + max[MissileLauncherAmmo] = 0; + max[Chaingun] = 0; + max[ChaingunAmmo] = 0; + max[RepairGun] = 1; + max[CloakingPack] = 0; + max[SensorJammerPack] = 0; + max[EnergyPack] = 0; + max[RepairPack] = 1; + max[ShieldPack] = 0; + max[AmmoPack] = 0; + max[SatchelCharge] = 0; + max[MortarBarrelPack] = 1; + max[MissileBarrelPack] = 1; + max[AABarrelPack] = 1; + max[PlasmaBarrelPack] = 1; + max[ELFBarrelPack] = 1; + max[InventoryDeployable] = 1; + max[MotionSensorDeployable] = 1; + max[PulseSensorDeployable] = 1; + max[TurretOutdoorDeployable] = 1; + max[TurretIndoorDeployable] = 1; + max[FlashGrenade] = 0; + max[ConcussionGrenade] = 0; + max[FlareGrenade] = 5; + max[TargetingLaser] = 1; + max[ELFGun] = 0; + max[ShockLance] = 0; + max[CameraGrenade] = 2; + max[Beacon] = 5; + //Guns + max[ConstructionTool] = 1; + max[NerfGun] = 1; + max[NerfBallLauncher] = 1; + max[NerfBallLauncherAmmo] = 25; + max[SuperChaingun] = 0; + max[SuperChaingunAmmo] = 0; + max[MergeTool] =1; + //Building parts + max[spineDeployable] = 1; + max[mspineDeployable] = 1; + max[wWallDeployable] = 1; + max[floorDeployable] = 1; + max[WallDeployable] = 1; + //Turrets + max[TurretLaserDeployable] = 1; + max[TurretMissileRackDeployable]= 1; + max[DiscTurretDeployable] = 0; + //Largepacks + max[EnergizerDeployable] = 0; + max[TreeDeployable] = 1; + max[CrateDeployable] = 1; + max[DecorationDeployable] = 1; + max[LogoProjectorDeployable] = 1; + max[LightDeployable] = 1; + max[TripwireDeployable] = 1; + max[TelePadPack] = 1; + max[TurretBasePack] = 1; + max[LargeInventoryDeployable] = 1; + max[GeneratorDeployable] = 1; + max[SolarPanelDeployable] = 1; + max[SwitchDeployable] = 1; + max[MediumSensorDeployable] = 1; + max[LargeSensorDeployable] = 1; + max[DoorDeployable] = 1; + //Misc + max[JumpadDeployable] = 1; + max[EscapePodDeployable] = 1; + max[ForceFieldDeployable] = 1; + max[GravityFieldDeployable] = 1; + + //Some small additions + //Note all that keeps us from full plugin compability is this code. + max[TractorGun] = 1; + max[TransGun] = 1; + max[VehiclePadPack] = 1; + max[mpm_beaconpack] = 1; + max[TurretMpm_Anti_Deployable] = 1; + max[EmitterDepPack] = 1; + max[AudioDepPack] = 1; + max[DispenserDepPack] = 1; + max[DetonationDepPack] = 1; + max[TransDepPack] = 1; + max[MpmFuelPack] = 1; + max[MpmAmmoPack] = 1; + + observeParameters = "0.5 4.5 4.5"; + shieldEffectScale = "0.7 0.7 1.0"; +}; + + +//---------------------------------------------------------------------------- +datablock PlayerData(PureFemaleHumanArmor) : PureMaleHumanArmor +{ + shapeFile = "light_female.dts"; + waterBreathSound = WaterBreathFemaleSound; + jetEffect = HumanMediumArmorJetEffect; +}; + +datablock PlayerData(PureMaleBiodermArmor) : PureMaleHumanArmor +{ + shapeFile = "bioderm_light.dts"; + jetEmitter = BiodermArmorJetEmitter; + jetEffect = BiodermArmorJetEffect; + + + debrisShapeName = "bio_player_debris.dts"; + + //Foot Prints + decalData = LightBiodermFootprint; + decalOffset = 0.3; + + waterBreathSound = WaterBreathBiodermSound; +}; + +// -------------------------------------------------------------------------- +// End True Build Armors +// -------------------------------------------------------------------------- + +//---------------------------------------------------------------------------- + +function Armor::onAdd(%data,%obj) +{ + Parent::onAdd(%data, %obj); + // Vehicle timeout + %obj.mountVehicle = true; + + // Default dynamic armor stats + %obj.setRechargeRate(%data.rechargeRate); + %obj.setRepairRate(0); + + %obj.setSelfPowered(); +} + +function Armor::onRemove(%this, %obj) +{ + //Frohny asked me to remove this - all players are deleted now on mission cycle... + //if(%obj.getState() !$= "Dead") + //{ + // error("ERROR PLAYER REMOVED WITHOUT DEATH - TRACE:"); + // trace(1); + // schedule(0,0,trace,0); + //} + + if (%obj.client.player == %obj) + %obj.client.player = 0; +} + +function Armor::onNewDataBlock(%this,%obj) +{ +} + +function Armor::onDisabled(%this,%obj,%state) +{ + %fadeTime = 1000; + %obj.startFade( %fadeTime, ($CorpseTimeoutValue) - %fadeTime, true ); + %obj.schedule($CorpseTimeoutValue, "delete"); +} + +function Armor::shouldApplyImpulse(%data, %obj) +{ + return true; +} + +$wasFirstPerson = true; + +function Armor::onMount(%this,%obj,%vehicle,%node) +{ +//[most] +if (%vehicle.base.leftpad == %vehicle || %vehicle.base.rightpad == %vehicle) + { + %node = 1; + %obj.mvehicle = %vehicle; + } +//[most] + + if (%node == 0) + { + // Node 0 is the pilot's pos. + %obj.setTransform("0 0 0 0 0 1 0"); + %obj.setActionThread(%vehicle.getDatablock().mountPose[%node],true,true); + + if(!%obj.inStation) + %obj.lastWeapon = (%obj.getMountedImage($WeaponSlot) == 0 ) ? "" : %obj.getMountedImage($WeaponSlot).getName().item; + + %obj.unmountImage($WeaponSlot); + + if(!%obj.client.isAIControlled()) + { + %obj.setControlObject(%vehicle); + %obj.client.setObjectActiveImage(%vehicle, 2); + } + + //E3 respawn... + + if(%obj == %obj.lastVehicle.lastPilot && %obj.lastVehicle != %vehicle) + { + schedule(240000, %obj.lastVehicle,"vehicleAbandonTimeOut", %obj.lastVehicle); + %obj.lastVehicle.lastPilot = ""; + } + if(%vehicle.lastPilot !$= "" && %vehicle == %vehicle.lastPilot.lastVehicle) + %vehicle.lastPilot.lastVehicle = ""; + + %vehicle.abandon = false; + %vehicle.lastPilot = %obj; + %obj.lastVehicle = %vehicle; + + // update the vehicle's team + if((%vehicle.getTarget() != -1) && %vehicle.getDatablock().cantTeamSwitch $= "") + { + setTargetSensorGroup(%vehicle.getTarget(), %obj.client.getSensorGroup()); + if( %vehicle.turretObject > 0 ) + setTargetSensorGroup(%vehicle.turretObject.getTarget(), %obj.client.getSensorGroup()); + } + + // Send a message to the client so they can decide if they want to change view or not: + commandToClient( %obj.client, 'VehicleMount' ); + + } + else + { + // tailgunner/passenger positions + if(%vehicle.getDataBlock().mountPose[%node] !$= "") + %obj.setActionThread(%vehicle.getDatablock().mountPose[%node]); + else + %obj.setActionThread("root", true); + } + // ------------------------------------------------------------------------- + // z0dd - ZOD, 10/06/02. announce to any other passengers that you've boarded + if(%vehicle.getDatablock().numMountPoints > 1) + { + %nodeName = findNodeName(%vehicle, %node); // function in vehicle.cs + for(%i = 0; %i < %vehicle.getDatablock().numMountPoints; %i++) + { + if (%vehicle.getMountNodeObject(%i) > 0) + { + if(%vehicle.getMountNodeObject(%i).client != %obj.client) + { + %team = (%obj.team == %vehicle.getMountNodeObject(%i).client.team ? 'Teammate' : 'Enemy'); + messageClient( %vehicle.getMountNodeObject(%i).client, 'MsgShowPassenger', '\c2%3: \c3%1\c2 has boarded in the \c3%2\c2 position.', %obj.client.name, %nodeName, %team ); + } + commandToClient( %vehicle.getMountNodeObject(%i).client, 'showPassenger', %node, true); + } + } + } + //make sure they don't have any packs active +// if ( %obj.getImageState( $BackpackSlot ) $= "activate") +// %obj.use("Backpack"); + if ( %obj.getImageTrigger( $BackpackSlot ) ) + %obj.setImageTrigger( $BackpackSlot, false ); + + //AI hooks + %obj.client.vehicleMounted = %vehicle; + AIVehicleMounted(%vehicle); + if(%obj.client.isAIControlled()) + %this.AIonMount(%obj, %vehicle, %node); +} + + +function Armor::onUnmount( %this, %obj, %vehicle, %node ) +{ + if ( %node == 0 ) + { + commandToClient( %obj.client, 'VehicleDismount' ); + commandToClient(%obj.client, 'removeReticle'); + + if(%obj.inv[%obj.lastWeapon]) + %obj.use(%obj.lastWeapon); + + if(%obj.getMountedImage($WeaponSlot) == 0) + %obj.selectWeaponSlot( 0 ); + + //Inform gunner position when pilot leaves... + //if(%vehicle.getDataBlock().showPilotInfo !$= "") + // if((%gunner = %vehicle.getMountNodeObject(1)) != 0) + // commandToClient(%gunner.client, 'PilotInfo', "PILOT EJECTED", 6, 1); + } + // ---------------------------------------------------------------------- + // z0dd - ZOD, 10/06/02. announce to any other passengers that you've left + if(%vehicle.getDatablock().numMountPoints > 1) + { + %nodeName = findNodeName(%vehicle, %node); // function in vehicle.cs + for(%i = 0; %i < %vehicle.getDatablock().numMountPoints; %i++) + { + if (%vehicle.getMountNodeObject(%i) > 0) + { + if(%vehicle.getMountNodeObject(%i).client != %obj.client) + { + %team = (%obj.team == %vehicle.getMountNodeObject(%i).client.team ? 'Teammate' : 'Enemy'); + messageClient( %vehicle.getMountNodeObject(%i).client, 'MsgShowPassenger', '\c2%3: \c3%1\c2 has ejected from the \c3%2\c2 position.', %obj.client.name, %nodeName, %team ); + } + commandToClient( %vehicle.getMountNodeObject(%i).client, 'showPassenger', %node, false); + } + } + } + //AI hooks + %obj.client.vehicleMounted = ""; + if(%obj.client.isAIControlled()) + %this.AIonUnMount(%obj, %vehicle, %node); +} + +$ammoType[0] = "PlasmaAmmo"; +$ammoType[1] = "DiscAmmo"; +$ammoType[2] = "GrenadeLauncherAmmo"; +$ammoType[3] = "MortarAmmo"; +$ammoType[4] = "MissileLauncherAmmo"; +$ammoType[5] = "ChaingunAmmo"; +// z0dd - ZOD, 9/13/02. TR2 weapons +$ammoType[6] = "TR2DiscAmmo"; +$ammoType[7] = "TR2GrenadeLauncherAmmo"; +$ammoType[8] = "TR2ChaingunAmmo"; +$ammoType[9] = "TR2MortarAmmo"; +$ammoType[10] = "NerfBallLauncherAmmo"; +$ammoType[11] = "SuperChaingunAmmo"; + +function Armor::onCollision(%this,%obj,%col,%forceVehicleNode) +{ + if (%obj.getState() $= "Dead") + return; + + %dataBlock = %col.getDataBlock(); + %className = %dataBlock.className; + %client = %obj.client; + // player collided with a vehicle + %node = -1; + if (%forceVehicleNode !$= "" || (%className $= WheeledVehicleData || %className $= FlyingVehicleData || %className $= HoverVehicleData) && + %obj.mountVehicle && %obj.getState() $= "Move" && %col.mountable && !%obj.inStation && %col.getDamageState() !$= "Destroyed") { + + // Escape pod + if (%dataBlock == EscapePodVehicle.getID()) { + if (%dataBlock.isBlocked(%col,%obj)) { + if (%col.blockedTime + 1000 < getSimTime()) { + %col.blockedTime = getSimTime(); + %col.play3D(TelePadAccessDeniedSound); + messageClient(%obj.client,'msgClient','\c2Unable to launch, escape pod is blocked!'); + } + return; + } + } + + //if the player is an AI, he should snap to the mount points in node order, + //to ensure they mount the turret before the passenger seat, regardless of where they collide... + if (%obj.client.isAIControlled()) + { + %transform = %col.getTransform(); + + //either the AI is *required* to pilot, or they'll pick the first available passenger seat + if (%client.pilotVehicle) + { + //make sure the bot is in light armor + if (%client.player.getArmorSize() $= "Light") + { + //make sure the pilot seat is empty + if (!%col.getMountNodeObject(0)) + %node = 0; + } + } + else + %node = findAIEmptySeat(%col, %obj); + } + else + %node = findEmptySeat(%col, %obj, %forceVehicleNode); + + //now mount the player in the vehicle + if(%node >= 0) + { + // players can't be pilots, bombardiers or turreteers if they have + // "large" packs -- stations, turrets, turret barrels + if(hasLargePack(%obj)) { + // check to see if attempting to enter a "sitting" node + if(nodeIsSitting(%datablock, %node)) { + // send the player a message -- can't sit here with large pack + if(!%obj.noSitMessage) + { + %obj.noSitMessage = true; + %obj.schedule(2000, "resetSitMessage"); + messageClient(%obj.client, 'MsgCantSitHere', '\c2Pack too large, can\'t occupy this seat.~wfx/misc/misc.error.wav'); + } + return; + } + } + if(%col.noEnemyControl && %obj.team != %col.team) + return; + + commandToClient(%obj.client,'SetDefaultVehicleKeys', true); + //If pilot or passenger then bind a few extra keys + if(%node == 0) + commandToClient(%obj.client,'SetPilotVehicleKeys', true); + else + commandToClient(%obj.client,'SetPassengerVehicleKeys', true); + + if(!%obj.inStation) + %col.lastWeapon = ( %col.getMountedImage($WeaponSlot) == 0 ) ? "" : %col.getMountedImage($WeaponSlot).getName().item; + else + %col.lastWeapon = %obj.lastWeapon; + + %obj.preVehicleMountPos = %obj.getPosition(); + + %col.mountObject(%obj,%node); + %col.playAudio(0, MountVehicleSound); + %obj.mVehicle = %col; + + // if player is repairing something, stop it + if(%obj.repairing) + stopRepairing(%obj); + + //this will setup the huds as well... + %dataBlock.playerMounted(%col,%obj, %node); + } + } + else if (%classname $= "energizer") + { + // only detonate on contact in non-purebuild mode + if ($Host::Purebuild == 0) { + %col.damage(%col, 0, 10, $DamageType::Ground); + %obj.damage(%col, 0, 10, $DamageType::Ground); + } + } + // TODO - keep these up to date + else if (%className $= "wall" || %className $= "wwall" || %className $= "spine" || %className $= "mspine" || %className $= "floor") { + %obj.playAudio(0,(GetRandom()*2 >1) ? LFootMediumMetalSound : RFootMediumMetalSound); + %obj.lastDepCol = %col; + %obj.lastDepColPos = %obj.getPosition(); + if (%className $= "wall") + doorfunction(%obj,%col); + } + else if (%className $= "Armor") { + // player has collided with another player + if(%col.getState() $= "Dead") { + %gotSomething = false; + // it's corpse-looting time! + // weapons -- don't pick up more than you are allowed to carry! + for(%i = 0; ( %obj.weaponCount < %obj.getDatablock().maxWeapons ) && $InvWeapon[%i] !$= ""; %i++) + { + %weap = $NameToInv[$InvWeapon[%i]]; + if ( %col.hasInventory( %weap ) ) + { + if ( %obj.incInventory(%weap, 1) > 0 ) + { + %col.decInventory(%weap, 1); + %gotSomething = true; + messageClient(%obj.client, 'MsgItemPickup', '\c0You picked up %1.', %weap.pickUpName); + } + } + } + // targeting laser: + if ( %col.hasInventory( "TargetingLaser" ) ) + { + if ( %obj.incInventory( "TargetingLaser", 1 ) > 0 ) + { + %col.decInventory( "TargetingLaser", 1 ); + %gotSomething = true; + messageClient( %obj.client, 'MsgItemPickup', '\c0You picked up a targeting laser.' ); + } + } + // ammo + for(%j = 0; $ammoType[%j] !$= ""; %j++) + { + %ammoAmt = %col.inv[$ammoType[%j]]; + if(%ammoAmt) + { + // incInventory returns the amount of stuff successfully grabbed + %grabAmt = %obj.incInventory($ammoType[%j], %ammoAmt); + if(%grabAmt > 0) + { + %col.decInventory($ammoType[%j], %grabAmt); + %gotSomething = true; + messageClient(%obj.client, 'MsgItemPickup', '\c0You picked up %1.', $ammoType[%j].pickUpName); + %obj.client.setWeaponsHudAmmo($ammoType[%j], %obj.getInventory($ammoType[%j])); + } + } + } + // figure out what type, if any, grenades the (live) player has + %playerGrenType = "None"; + for(%x = 0; $InvGrenade[%x] !$= ""; %x++) { + %gren = $NameToInv[$InvGrenade[%x]]; + %playerGrenAmt = %obj.inv[%gren]; + if(%playerGrenAmt > 0) + { + %playerGrenType = %gren; + break; + } + } + // grenades + for(%k = 0; $InvGrenade[%k] !$= ""; %k++) + { + %gren = $NameToInv[$InvGrenade[%k]]; + %corpseGrenAmt = %col.inv[%gren]; + // does the corpse hold any of this grenade type? + if(%corpseGrenAmt) + { + // can the player pick up this grenade type? + if((%playerGrenType $= "None") || (%playerGrenType $= %gren)) + { + %taken = %obj.incInventory(%gren, %corpseGrenAmt); + if(%taken > 0) + { + %col.decInventory(%gren, %taken); + %gotSomething = true; + messageClient(%obj.client, 'MsgItemPickup', '\c0You picked up %1.', %gren.pickUpName); + %obj.client.setInventoryHudAmount(%gren, %obj.getInventory(%gren)); + } + } + break; + } + } + // figure out what type, if any, mines the (live) player has + %playerMineType = "None"; + for(%y = 0; $InvMine[%y] !$= ""; %y++) + { + %mType = $NameToInv[$InvMine[%y]]; + %playerMineAmt = %obj.inv[%mType]; + if(%playerMineAmt > 0) + { + %playerMineType = %mType; + break; + } + } + // mines + for(%l = 0; $InvMine[%l] !$= ""; %l++) + { + %mine = $NameToInv[$InvMine[%l]]; + %mineAmt = %col.inv[%mine]; + if(%mineAmt) { + if((%playerMineType $= "None") || (%playerMineType $= %mine)) + { + %grabbed = %obj.incInventory(%mine, %mineAmt); + if(%grabbed > 0) + { + %col.decInventory(%mine, %grabbed); + %gotSomething = true; + messageClient(%obj.client, 'MsgItemPickup', '\c0You picked up %1.', %mine.pickUpName); + %obj.client.setInventoryHudAmount(%mine, %obj.getInventory(%mine)); + } + } + break; + } + } + // beacons + %beacAmt = %col.inv[Beacon]; + if(%beacAmt) + { + %bTaken = %obj.incInventory(Beacon, %beacAmt); + if(%bTaken > 0) + { + %col.decInventory(Beacon, %bTaken); + %gotSomething = true; + messageClient(%obj.client, 'MsgItemPickup', '\c0You picked up %1.', Beacon.pickUpName); + %obj.client.setInventoryHudAmount(Beacon, %obj.getInventory(Beacon)); + } + } + // repair kit + %rkAmt = %col.inv[RepairKit]; + if(%rkAmt) + { + %rkTaken = %obj.incInventory(RepairKit, %rkAmt); + if(%rkTaken > 0) + { + %col.decInventory(RepairKit, %rkTaken); + %gotSomething = true; + messageClient(%obj.client, 'MsgItemPickup', '\c0You picked up %1.', RepairKit.pickUpName); + %obj.client.setInventoryHudAmount(RepairKit, %obj.getInventory(RepairKit)); + } + } + } + else if ($PlayerSnapTo == true) { + if (!isObject(%col.getMountedObject(0))) { + if (!isObject(%obj.getMountedObject(0)) || %obj.getMountedObject(0) != %col) { + %col.mountObject(%obj,$BackPackSlot); + %gotSomething = true; + } + } + } + else if ($NaughtyMode == true) { + playPain(%obj); + playPain(%col); + } + else if ($AngstMode == true) { + playDeathCry(%obj); + playDeathCry(%col); + } + if ($JumpyMode == true) { + %obj.applyImpulse(%obj.getPosition(),"0 0 500"); + %col.applyImpulse(%col.getPosition(),"0 0 500"); + } + if (%obj.client.race $= "Human" && $SexChangeMode == true) { + if (%obj.client.oldSex $= "") + %obj.client.oldSex = %obj.client.sex; + if (%obj.client.oldVoice $= "") + %obj.client.oldVoice = %obj.client.voice; + %voice = getTaggedString(getTargetVoice(%obj.client.target)); + %voiceNum = getSubStr(%voice,strLen(%voice)-1,1); + if (%obj.client.sex $= "Male") { + %obj.client.sex = "Female"; + %obj.client.voiceTag = addTaggedString("Fem" @ %voiceNum); + setTargetVoice(%obj.client.target,%obj.client.voiceTag); + } + else { + %obj.client.sex = "Male"; + %obj.client.voiceTag = addTaggedString("Male" @ %voiceNum); + setTargetVoice(%obj.client.target,%obj.client.voiceTag); + } + %obj.setArmor(%client.armor); + } + if(%gotSomething) + %col.playAudio(0, CorpseLootingSound); + } +} + +function Player::resetSitMessage(%obj) +{ + %obj.noSitMessage = false; +} + +function Player::setInvincible(%this, %val) +{ + %this.invincible = %val; +} + +function Player::causedRecentDamage(%this, %val) +{ + %this.causedRecentDamage = %val; +} + +function hasLargePack(%player) +{ + %pack = %player.getMountedImage($BackpackSlot); + if(%pack.isLarge) + return true; + else + return false; +} + +function nodeIsSitting(%vehDBlock, %node) +{ + // pilot == always a "sitting" node + if(%node == 0) + return true; + else { + switch$ (%vehDBlock.getName()) + { + // note: for assault tank -- both nodes are sitting + // for any single-user vehicle -- pilot node is sitting + case "BomberFlyer": + // bombardier == sitting; tailgunner == not sitting + if(%node == 1) + return true; + else + return false; + case "HAPCFlyer": + // only the pilot node is sitting + return false; + case "SuperHAPCFlyer": + // only the pilot node is sitting + return false; + default: + return true; + } + } +} + +//---------------------------------------------------------------------------- +function Player::setMountVehicle(%this, %val) +{ + %this.mountVehicle = %val; +} + +function Armor::doDismount(%this, %obj, %forced,%eject) { + // This function is called by player.cc when the jump trigger + // is true while mounted + if (!%obj.isMounted()) + return; + //[most] emp hook + if (%obj.isemped) + return; + //[most] + + %vehicle = %obj.getObjectMount(); + %vehicleData = %vehicle.getDataBlock(); + + if (%vehicleData == EscapePodVehicle.getID()) { + if (%vehicle.playerMountedTime + 4000 > getSimTime()) + return; + } + + if(isObject(%obj.getObjectMount().shield)) + %obj.getObjectMount().shield.delete(); + + commandToClient(%obj.client,'SetDefaultVehicleKeys', false); + + if (%Eject) + %push = 30; + else + %push = 1; + + + // Position above dismount point + + %pos = getWords(%obj.getTransform(), 0, 2); + %oldPos = %pos; + %vec[0] = " 0 0 1"; + %vec[1] = " 0 0 1"; + %vec[2] = " 0 0 -1"; + %vec[3] = " 1 0 0"; + %vec[4] = "-1 0 0"; + %numAttempts = 5; + %success = -1; + %impulseVec = "0 0 0"; + if (%obj.getObjectMount().getDatablock().hasDismountOverrides() == true) + { + %vec[0] = %obj.getObjectMount().getDatablock().getDismountOverride(%obj.getObjectMount(), %obj); + %vec[0] = MatrixMulVector(%obj.getObjectMount().getTransform(), %vec[0]); + } + else + { + %vec[0] = MatrixMulVector( %obj.getTransform(), %vec[0]); + } + + %pos = "0 0 0"; + for (%i = 0; %i < %numAttempts; %i++) + { + %pos = VectorAdd(%oldPos, VectorScale(%vec[%i], 3)); + if (%obj.checkDismountPoint(%oldPos, %pos)) + { + %success = %i; + %impulseVec = %vec[%i]; + break; + } + } + if (%forced && %success == -1) + { + %pos = %oldPos; + } + + // hide the dashboard HUD and delete elements based on node + commandToClient(%obj.client, 'setHudMode', 'Standard', "", 0); + // Unmount and control body + if(%obj.vehicleTurret) + %obj.vehicleTurret.getDataBlock().playerDismount(%obj.vehicleTurret); + %obj.unmount(); + if(%obj.mVehicle) + %obj.mVehicle.getDataBlock().playerDismounted(%obj.mVehicle, %obj); + + // bots don't change their control objects when in vehicles + if(!%obj.client.isAIControlled()) + { + %vehicle = %obj.getControlObject(); + %obj.setControlObject(0); + } + + %obj.mountVehicle = false; + %obj.schedule(4000, "setMountVehicle", true); + + // Position above dismount point + %obj.setTransform(%pos); + %obj.playAudio(0, UnmountVehicleSound); + %obj.applyImpulse(%pos, VectorScale(%impulseVec, %obj.getDataBlock().mass * 3 * %push)); + //%obj.applyImpulse(%pos, VectorScale(%impulseVec, %obj.getDataBlock().mass * 3)); + %obj.setPilot(false); + %obj.vehicleTurret = ""; +} + +function resetObserveFollow( %client, %dismount ) +{ + if( %dismount ) + { + if( !isObject( %client.player ) ) + return; + + for( %i = 0; %i < %client.observeCount; %i++ ) + { + if (isObject(%client.observers[%i].camera)) + %client.observers[%i].camera.setOrbitMode( %client.player, %client.player.getTransform(), 0.5, 4.5, 4.5); + } + } + else + { + if( !%client.player.isMounted() ) + return; + + // grab the vehicle... + %mount = %client.player.getObjectMount(); + if( %mount.getDataBlock().observeParameters $= "" ) + %params = %client.player.getTransform(); + else + %params = %mount.getDataBlock().observeParameters; + + for( %i = 0; %i < %client.observeCount; %i++ ) + { + if (isObject(%client.observers[%i].camera)) + %client.observers[%i].camera.setOrbitMode(%mount, %mount.getTransform(), getWord( %params, 0 ), getWord( %params, 1 ), getWord( %params, 2 )); + } + } +} + + +//---------------------------------------------------------------------------- + +function Player::scriptKill(%player, %damageType) +{ + %player.scriptKilled = 1; + %player.setInvincible(false); + %player.damage(0, %player.getPosition(), 10000, %damageType); +} + +function Armor::damageObject(%data, %targetObject, %sourceObject, %position, %amount, %damageType, %momVec, %mineSC) { +// error("Armor::damageObject( "@%data@", "@%targetObject@", "@%sourceObject@", "@%position@", "@%amount@", "@%damageType@", "@%momVec@" )"); + if (%targetObject.invincible || %targetObject.getState() $= "Dead" + || ((%targetObject.client.isJailed || %targetObject.client.permInvincible) && !%targetObject.scriptKilled)) + return; + + + //---------------------------------------------------------------- + // z0dd - ZOD, 6/09/02. Check to see if this vehcile is destroyed, + // if it is do no damage. Fixes vehicle ghosting bug. We do not + // check for isObject here, destroyed objects fail it even though + // they exist as objects, go figure. + if(%damageType == $DamageType::Impact) + if(%sourceObject.getDamageState() $= "Destroyed") + return; + + if (%targetObject.isMounted() && %targetObject.scriptKilled $= "") + { + %mount = %targetObject.getObjectMount(); + if(%mount.team == %targetObject.team) + { + %found = -1; + for (%i = 0; %i < %mount.getDataBlock().numMountPoints; %i++) + { + if (%mount.getMountNodeObject(%i) == %targetObject) + { + %found = %i; + break; + } + } + + if (%found != -1) + { + if (%mount.getDataBlock().isProtectedMountPoint[%found]) + { + %mount.getDataBlock().damageObject(%mount, %sourceObject, %position, %amount, %damageType); + return; + } + } + } + } + + %targetClient = %targetObject.getOwnerClient(); + if(isObject(%mineSC)) + %sourceClient = %mineSC; + else + %sourceClient = isObject(%sourceObject) ? %sourceObject.getOwnerClient() : 0; + + %targetTeam = %targetClient.team; + + //if the source object is a player object, player's don't have sensor groups + // if it's a turret, get the sensor group of the target + // if its a vehicle (of any type) use the sensor group + if (%sourceClient) + %sourceTeam = %sourceClient.getSensorGroup(); + else if(%damageType == $DamageType::Suicide) + %sourceTeam = 0; + + //-------------------------------------------------------------------------------------------------------------------- + // z0dd - ZOD, 5/8/02. Check to see if this turret has a valid owner, if not clear the owner varible. + //else if(isObject(%sourceObject) && %sourceObject.getClassName() $= "Turret") + // %sourceTeam = getTargetSensorGroup(%sourceObject.getTarget()); + else if(isObject(%sourceObject) && %sourceObject.getClassName() $= "Turret") + { + %sourceTeam = getTargetSensorGroup(%sourceObject.getTarget()); + if(%sourceObject.getOwner() !$="" && (%sourceObject.getOwner().team != %sourceObject.team || !isObject(%sourceObject.getOwner()))) + %sourceObject.setOwner(); + } + // End z0dd - ZOD + //-------------------------------------------------------------------------------------------------------------------- + else if( isObject(%sourceObject) && + ( %sourceObject.getClassName() $= "FlyingVehicle" || %sourceObject.getClassName() $= "WheeledVehicle" || %sourceObject.getClassName() $= "HoverVehicle")) + %sourceTeam = getTargetSensorGroup(%sourceObject.getTarget()); + else + { + if (isObject(%sourceObject) && %sourceObject.getTarget() >= 0 ) + { + %sourceTeam = getTargetSensorGroup(%sourceObject.getTarget()); + } + else + { + %sourceTeam = -1; + } + } + + // if teamdamage is off, and both parties are on the same team + // (but are not the same person), apply no damage + if(!$teamDamage && (%targetClient != %sourceClient) && (%targetTeam == %sourceTeam)) + return; + + if(%targetObject.isShielded && %damageType != $DamageType::Blaster) + %amount = %data.checkShields(%targetObject, %position, %amount, %damageType); + + if(%amount == 0) + return; + + // Set the damage flash + %damageScale = %data.damageScale[%damageType]; + if(%damageScale !$= "") + %amount *= %damageScale; + + %flash = %targetObject.getDamageFlash() + (%amount * 2); + if (%flash > 0.75) + %flash = 0.75; + + %previousDamage = %targetObject.getDamagePercent(); + %targetObject.setDamageFlash(%flash); + + if ($Host::InvincibleArmors == 1 && !%targetObject.scriptKilled) { + if ((%sourceObject.team != %targetObject.team) || Game.numTeams == 1) { + %wp = new WayPoint() { + position = %targetObject.getWorldBoxCenter(); + dataBlock = "WayPointMarker"; + team = (%sourceObject.team == %targetObject.team) ? 0 : %sourceObject.team; + name = mFloatLength((100 / %data.maxDamage) * %amount,0) @ "%"; + }; + MissionCleanup.add(%wp); + %wp.schedule(1500,delete); + } + } + else + %targetObject.applyDamage(%amount); + + Game.onClientDamaged(%targetClient, %sourceClient, %damageType, %sourceObject); + + %targetClient.lastDamagedBy = %damagingClient; + %targetClient.lastDamaged = getSimTime(); + + //now call the "onKilled" function if the client was... you know... + if(%targetObject.getState() $= "Dead") + { + // where did this guy get it? + %damLoc = %targetObject.getDamageLocation(%position); + + // should this guy be blown apart? + if( %damageType == $DamageType::Explosion || + %damageType == $DamageType::TankMortar || + %damageType == $DamageType::Mortar || + %damageType == $DamageType::MortarTurret || + %damageType == $DamageType::BomberBombs || + %damageType == $DamageType::SatchelCharge || + %damageType == $DamageType::Missile ) + { + if( %previousDamage >= 0.35 ) // only if <= 35 percent damage remaining + { + %targetObject.setMomentumVector(%momVec); + %targetObject.blowup(); + } + } + + // this should be funny... + if( %damageType == $DamageType::VehicleSpawn ) + { + %targetObject.setMomentumVector("0 0 1"); + %targetObject.blowup(); + } + + // If we were killed, max out the flash + %targetObject.setDamageFlash(0.75); + + %damLoc = %targetObject.getDamageLocation(%position); + Game.onClientKilled(%targetClient, %sourceClient, %damageType, %sourceObject, %damLoc); + } + else if ( %amount > 0.1 ) + { + if( %targetObject.station $= "" && %targetObject.isCloaked() ) + { + %targetObject.setCloaked( false ); + %targetObject.reCloak = %targetObject.schedule( 500, "setCloaked", true ); + } + + playPain( %targetObject ); + } +} + +function Armor::onImpact(%data, %playerObject, %collidedObject, %vec, %vecLen) { + %data.damageObject(%playerObject, 0, VectorAdd(%playerObject.getPosition(),%vec), + %vecLen * %data.speedDamageScale , $DamageType::Ground); +// if (%collidedObject & $TypeMasks::PlayerObjectType) { +// if (%collidedObject.getState() !$= "Dead") { +// %data.damageObject(%collidedObject, 0, VectorAdd(%playerObject.getPosition(),%vec), +// %vecLen * %data.speedDamageScale , $DamageType::Ground); +// } +// } +} + +function Armor::applyConcussion( %this, %dist, %radius, %sourceObject, %targetObject ) +{ + %percentage = 1 - ( %dist / %radius ); + %random = getRandom(); + + if( %sourceObject == %targetObject ) + { + %flagChance = 1.0; + %itemChance = 1.0; + } + else + { + %flagChance = 0.7; + %itemChance = 0.7; + } + + %probabilityFlag = %flagChance * %percentage; + %probabilityItem = %itemChance * %percentage; + + if( %random <= %probabilityFlag ) + { + Game.applyConcussion( %targetObject ); + } + + if( %random <= %probabilityItem ) + { + %player = %targetObject; + %numWeapons = 0; + + // blaster 0 + // plasma 1 + // chain 2 + // disc 3 + // grenade 4 + // snipe 5 + // elf 6 + // mortar 7 + // nerfgun 8 + // NerfBallLauncher 9 + // superchaingun 10 + + //get our inventory + if( %weaps[0] = %player.getInventory("Blaster") > 0 ) %numWeapons++; + if( %weaps[1] = %player.getInventory("Plasma") > 0 ) %numWeapons++; + if( %weaps[2] = %player.getInventory("Chaingun") > 0 ) %numWeapons++; + if( %weaps[3] = %player.getInventory("Disc") > 0 ) %numWeapons++; + if( %weaps[4] = %player.getInventory("GrenadeLauncher") > 0 ) %numWeapons++; + if( %weaps[5] = %player.getInventory("SniperRifle") > 0 ) %numWeapons++; + if( %weaps[6] = %player.getInventory("ELFGun") > 0 ) %numWeapons++; + if( %weaps[7] = %player.getInventory("Mortar") > 0 ) %numWeapons++; + if( %weaps[8] = %player.getInventory("NerfGun") > 0 ) %numWeapons++; + if( %weaps[9] = %player.getInventory("NerfBallLauncher") > 0 ) %numWeapons++; + if( %weaps[10] = %player.getInventory("SuperChaingun") > 0 ) %numWeapons++; + + %foundWeapon = false; + %attempts = 0; + + if( %numWeapons > 0 ) + { + while( !%foundWeapon ) + { + %rand = mFloor( getRandom() * 11 ); + if( %weaps[ %rand ] ) + { + %foundWeapon = true; + + switch ( %rand ) + { + case 0: + %player.use("Blaster"); + case 1: + %player.use("Plasma"); + case 2: + %player.use("Chaingun"); + case 3: + %player.use("Disc"); + case 4: + %player.use("GrenadeLauncher"); + case 5: + %player.use("SniperRifle"); + case 6: + %player.use("ElfGun"); + case 7: + %player.use("Mortar"); + case 8: + %player.use("NerfGun"); + case 9: + %player.use("NerfBallLauncher"); + case 10: + %player.use("SuperChaingun"); + } + + %image = %player.getMountedImage( $WeaponSlot ); + %player.throw( %image.item ); + %player.client.setWeaponsHudItem( %image.item, 0, 0 ); + %player.throwPack(); + } + else + { + %attempts++; + if( %attempts > 10 ) + %foundWeapon = true; + } + } + } + else + { + %targetObject.throwPack(); + %targetObject.throwWeapon(); + } + } +} + +//---------------------------------------------------------------------------- + +$DeathCry[1] = 'avo.deathCry_01'; +$DeathCry[2] = 'avo.deathCry_02'; +$PainCry[1] = 'avo.grunt'; +$PainCry[2] = 'avo.pain'; + +function playDeathCry( %obj ) +{ + %client = %obj.client; + %random = getRandom(1) + 1; + %desc = AudioClosest3d; + + playTargetAudio( %client.target, $DeathCry[%random], %desc, false ); +} + +function playPain( %obj ) +{ + %client = %obj.client; + %random = getRandom(1) + 1; + %desc = AudioClosest3d; + + playTargetAudio( %client.target, $PainCry[%random], %desc, false); +} + +//---------------------------------------------------------------------------- + +//$DefaultPlayerArmor = LightMaleHumanArmor; +$DefaultPlayerArmor = Light; + +function Player::setArmor(%this,%size) +{ + // Takes size as "Light","Medium", "Heavy" + %client = %this.client; + if (%client.race $= "Bioderm") + // Only have male bioderms. + %armor = %size @ "Male" @ %client.race @ Armor; + else + %armor = %size @ %client.sex @ %client.race @ Armor; + //echo("Player::armor: " @ %armor); + %this.setDataBlock(%armor); + %client.armor = %size; +} + +function getDamagePercent(%maxDmg, %dmgLvl) +{ + return (%dmgLvl / %maxDmg); +} + +function Player::getArmorSize(%this) +{ + // return size as "Light","Medium", "Heavy" + %dataBlock = %this.getDataBlock().getName(); + if (getSubStr(%dataBlock, 0, 5) $= "Light") + return "Light"; + else if (getSubStr(%dataBlock, 0, 6) $= "Medium") + return "Medium"; + else if (getSubStr(%dataBlock, 0, 5) $= "Heavy") + return "Heavy"; + else if (getSubStr(%dataBlock, 0, 4) $= "Pure") + return "Pure"; + else if (getSubStr(%dataBlock, 0, 8) $= "TR2Light") + return "TR2Light"; + else if (getSubStr(%dataBlock, 0, 9) $= "TR2Medium") + return "TR2Medium"; + else if (getSubStr(%dataBlock, 0, 8) $= "TR2Heavy") + return "TR2Heavy"; + else + return "Unknown"; +} + +function Player::pickup(%this,%obj,%amount) +{ + if (%this.client.isJailed) + return 0; + %data = %obj.getDataBlock(); + // Don't pick up a pack if we already have one mounted + if (%data.className $= Pack && + %this.getMountedImage($BackpackSlot) != 0) + return 0; + // don't pick up a weapon (other than targeting laser) if player's at maxWeapons + else if(%data.className $= Weapon + && %data.getName() !$= "TargetingLaser" // Special case + && %this.weaponCount >= %this.getDatablock().maxWeapons) + return 0; + // don't allow players to throw large packs at pilots (thanks Wizard) + else if(%data.className $= Pack && %data.image.isLarge && %this.isPilot()) + return 0; + return ShapeBase::pickup(%this,%obj,%amount); +} + +function Player::use( %this,%data ) +{ + // If player is in a station then he can't use any items + if(%this.station !$= "") + return false; + + // Convert the word "Backpack" to whatever is in the backpack slot. + if ( %data $= "Backpack" ) + { + if ( %this.inStation ) + return false; + + if ( %this.isPilot() ) + { + %vehicle = %this.getObjectMount(); + if (%vehicle.getDataBlock().getName() $= "MobileBaseVehicle" && $Host::Purebuild == 1) { + %vehicle.applyImpulse(%vehicle.getPosition(),"0 0 8000"); + return( false ); + } + //[most] + else if (%vehicle.base.leftpad == %vehicle) + { + PressButton(%vehicle,%this,0,0); + } + else if (%vehicle.base.rightpad == %vehicle) + { + PressButton(%vehicle,%this,1,0); + } + //[most] + else { + messageClient( %this.client, 'MsgCantUsePack', '\c2You can\'t use your pack while piloting.~wfx/misc/misc.error.wav' ); + return( false ); + } + } + else if ( %this.isWeaponOperator() ) + { + messageClient( %this.client, 'MsgCantUsePack', '\c2You can\'t use your pack while in a weaponry position.~wfx/misc/misc.error.wav' ); + return( false ); + } + + %image = %this.getMountedImage( $BackpackSlot ); + if ( %image ) + %data = %image.item; + } + + // Can't use some items when piloting or your a weapon operator + if ( %this.isPilot() || %this.isWeaponOperator() ) + if (isObject(%data) && %data.getName() !$= "RepairKit" ) + return false; + // Convert the word "Backpack" to whatever is in the backpack slot. + //[most] + if (isObject(%data) && %data.getName() $= "RepairKit" ) + { + if ( %this.isPilot() ) + { + %vehicle = %this.getObjectMount(); + if (%vehicle.base.leftpad == %vehicle) + { + PressButton(%vehicle,%this,0,1); + } + else if (%vehicle.base.rightpad == %vehicle) + { + PressButton(%vehicle,%this,1,1); + } + + } + } + //[most] + + return ShapeBase::use( %this, %data ); +} + +function Player::maxInventory(%this,%data) +{ + %max = ShapeBase::maxInventory(%this,%data); + if (%this.getInventory(AmmoPack)) + %max += AmmoPack.max[%data.getName()]; + return %max; +} + +function Player::isPilot(%this) +{ + %vehicle = %this.getObjectMount(); + // There are two "if" statements to avoid a script warning. + if (%vehicle) + if (%vehicle.getMountNodeObject(0) == %this) + return true; + return false; +} + +function Player::isWeaponOperator(%this) +{ + %vehicle = %this.getObjectMount(); + if ( %vehicle ) + { + %weaponNode = %vehicle.getDatablock().weaponNode; + if ( %weaponNode > 0 && %vehicle.getMountNodeObject( %weaponNode ) == %this ) + return( true ); + } + + return( false ); +} + +function Player::liquidDamage(%obj, %data, %damageAmount, %damageType) +{ + if(%obj.getState() !$= "Dead") + { + %data.damageObject(%obj, 0, "0 0 0", %damageAmount, %damageType); + %obj.lDamageSchedule = %obj.schedule(50, "liquidDamage", %data, %damageAmount, %damageType); + } + else + %obj.lDamageSchedule = ""; +} + +function Armor::onEnterLiquid(%data, %obj, %coverage, %type) +{ + switch(%type) + { + case 0: + //Water + case 1: + //Ocean Water + case 2: + //River Water + case 3: + //Stagnant Water + case 4: + //Lava + %obj.liquidDamage(%data, $DamageLava, $DamageType::Lava); + case 5: + //Hot Lava + %obj.liquidDamage(%data, $DamageHotLava, $DamageType::Lava); + case 6: + //Crusty Lava + %obj.liquidDamage(%data, $DamageCrustyLava, $DamageType::Lava); + case 7: + //Quick Sand + } +} + +function Armor::onLeaveLiquid(%data, %obj, %type) +{ + switch(%type) + { + case 0: + //Water + case 1: + //Ocean Water + case 2: + //River Water + case 3: + //Stagnant Water + case 4: + //Lava + case 5: + //Hot Lava + case 6: + //Crusty Lava + case 7: + //Quick Sand + } + + if(%obj.lDamageSchedule !$= "") + { + cancel(%obj.lDamageSchedule); + %obj.lDamageSchedule = ""; + } +} + +function Armor::onTrigger(%data, %player, %triggerNum, %val) +{ + if (%triggerNum == 4) + { + // Throw grenade + if (%val == 1) + { + %player.grenTimer = 1; + } + else + { + if (%player.grenTimer == 0) + { + // Bad throw for some reason + } + else + { + %player.use(Grenade); + %player.grenTimer = 0; + } + } + } + else if (%triggerNum == 5) + { + // Throw mine + if (%val == 1) + { + %player.mineTimer = 1; + } + else + { + if (%player.mineTimer == 0) + { + // Bad throw for some reason + } + else + { + %player.use(Mine); + %player.mineTimer = 0; + } + } + } + else if (%triggerNum == 3) + { + // val = 1 when jet key (LMB) first pressed down + // val = 0 when jet key released + // MES - do we need this at all any more? + if(%val == 1) + %player.isJetting = true; + else + %player.isJetting = false; + } +} + +function Player::setMoveState(%obj, %move) +{ + %obj.disableMove(%move); +} + +function Armor::onLeaveMissionArea(%data, %obj) +{ + Game.leaveMissionArea(%data, %obj); +} + +function Armor::onEnterMissionArea(%data, %obj) +{ + Game.enterMissionArea(%data, %obj); +} + +function Armor::animationDone(%data, %obj) +{ + if(%obj.animResetWeapon !$= "") + { + if(%obj.getMountedImage($WeaponSlot) == 0) + if(%obj.inv[%obj.lastWeapon]) + %obj.use(%obj.lastWeapon); + %obj.animSetWeapon = ""; + } +} + +function playDeathAnimation(%player, %damageLocation, %type) +{ + %vertPos = firstWord(%damageLocation); + %quadrant = getWord(%damageLocation, 1); + + //echo("vert Pos: " @ %vertPos); + //echo("quad: " @ %quadrant); + + if( %type == $DamageType::Explosion || %type == $DamageType::Mortar || %type == $DamageType::Grenade) + { + if(%quadrant $= "front_left" || %quadrant $= "front_right") + %curDie = $PlayerDeathAnim::ExplosionBlowBack; + else + %curDie = $PlayerDeathAnim::TorsoBackFallForward; + } + else if(%vertPos $= "head") + { + if(%quadrant $= "front_left" || %quadrant $= "front_right" ) + %curDie = $PlayerDeathAnim::HeadFrontDirect; + else + %curDie = $PlayerDeathAnim::HeadBackFallForward; + } + else if(%vertPos $= "torso") + { + if(%quadrant $= "front_left" ) + %curDie = $PlayerDeathAnim::TorsoLeftSpinDeath; + else if(%quadrant $= "front_right") + %curDie = $PlayerDeathAnim::TorsoRightSpinDeath; + else if(%quadrant $= "back_left" ) + %curDie = $PlayerDeathAnim::TorsoBackFallForward; + else if(%quadrant $= "back_right") + %curDie = $PlayerDeathAnim::TorsoBackFallForward; + } + else if (%vertPos $= "legs") + { + if(%quadrant $= "front_left" || %quadrant $= "back_left") + %curDie = $PlayerDeathAnim::LegsLeftGimp; + if(%quadrant $= "front_right" || %quadrant $= "back_right") + %curDie = $PlayerDeathAnim::LegsRightGimp; + } + + if(%curDie $= "" || %curDie < 1 || %curDie > 11) + %curDie = 1; + + %player.setActionThread("Death" @ %curDie); +} + +function Armor::onDamage(%data, %obj) +{ + if(%obj.station !$= "" && %obj.getDamageLevel() == 0) + %obj.station.getDataBlock().endRepairing(%obj.station); +} diff --git a/scripts/power.cs b/scripts/power.cs new file mode 100644 index 0000000..2f8d879 --- /dev/null +++ b/scripts/power.cs @@ -0,0 +1,358 @@ +$PowerThread = 0; +$AmbientThread = 1; +$ActivateThread = 2; +$DeployThread = 3; + +$HumSound = 0; +$ActivateSound = 1; +$DeploySound = 2; +$PlaySound = 3; + +//****************************************************************************** +//* Power -Audio- Data Blocks * +//****************************************************************************** + +datablock AudioProfile(BasePowerOn) +{ + filename = "fx/powered/base_power_on.wav"; + description = Audio2D; + preload = true; +}; + +datablock AudioProfile(BasePowerOff) +{ + filename = "fx/powered/base_power_off.wav"; + description = Audio2D; + preload = true; +}; + +datablock AudioProfile(BasePowerHum) +{ + filename = "fx/powered/base_power_loop.wav"; + description = AudioLooping2D; + preload = true; +}; + +//****************************************************************************** +//* Power - Functions * +//****************************************************************************** + +function GameBase::clearPower(%this) +{ +} + +function SimGroup::clearPower(%this) +{ + %this.powerCount = 0; + for (%i = 0; %i < %this.getCount(); %i++) + { + %obj = %this.getObject(%i); + if(%obj.getType() & $TypeMasks::GameBaseObjectType) + %obj.clearPower(); + } +} + +function SimObject::powerInit(%this, %powerCount) +{ + //function declared to reduce console error msg spam +} + +function SimGroup::powerInit(%this, %powerCount) +{ + if(%this.providesPower) + %powerCount++; + + %count = %this.getCount(); + for (%i = 0; %i < %count; %i++) + { + %obj = %this.getObject(%i); + if(%obj.getType() & $TypeMasks::GameBaseObjectType) + { + if(%obj.getDatablock().isPowering(%obj)) + %powerCount++; + } + } + %this.powerCount = %powerCount; + for (%i = 0; %i < %this.getCount(); %i++) + { + %obj = %this.getObject(%i); + %obj.powerInit(%powerCount); + } +} + +function GameBase::powerInit(%this, %powerCount) +{ + if(%powerCount) + %this.getDatablock().gainPower(%this); + else + %this.getDataBlock().losePower(%this); +} + +function SimObject::isPowering(%data, %obj) +{ + return false; +} + +function Generator::isPowering(%data, %obj) +{ + return !%obj.isDisabled(); +} + +function SimObject::updatePowerCount() +{ +} + +function SimObject::powerCheck() +{ +} + + +function SimGroup::updatePowerCount(%this, %value) +{ + if(%this.powerCount > 0 || %value > 0) + %this.powerCount += %value; + for (%i = 0; %i < %this.getCount(); %i++) + { + %this.getObject(%i).updatePowerCount(%value); + } + for (%i = 0; %i < %this.getCount(); %i++) + %this.getObject(%i).powerCheck(%this.powerCount); +} + +function GameBaseData::gainPower(%data, %obj) +{ +} + +function GameBaseData::losePower(%data, %obj) +{ +} + +function InteriorInstance::powerCheck(%this, %powerCount) +{ + if(%powerCount > 0) + %mode = "Off"; + else + %mode = "On"; + %this.setAlarmMode(%mode); +} + +function GameBase::powerCheck(%this, %powerCount) +{ + if(%powerCount || %this.selfPower) + %this.getDatablock().gainPower(%this); + else + %this.getDatablock().losePower(%this); +} + +function GameBase::incPowerCount(%this) { + %group = %this.getGroup(); + if (%group != nameToID("MissionCleanup/Deployables")) + %group.updatePowerCount(1); +} + +function GameBase::decPowerCount(%this) { + %group = %this.getGroup(); + if (%group != nameToID("MissionCleanup/Deployables")) + %group.updatePowerCount(-1); +} + +function GameBase::setSelfPowered(%this) { + if(!%this.isPowered()) { + %this.selfPower = true; + if(%this.getDatablock().deployedObject) + %this.initDeploy = true; + %this.getDataBlock().gainPower(%this); + } + else + %this.selfPower = true; +} + +function GameBase::clearSelfPowered(%this) +{ + %this.selfPower = ""; + if(!%this.isPowered()) + %this.getDataBlock().losePower(%this); +} + +function GameBase::isPowered(%this) { + return ((%this.selfPower && %this.isEnabled()) || %this.getGroup().powerCount > 0 || %this.powerCount > 0) && !%this.isSwitchedOff; +} + +function buildPowerList() { + $PowerList = ""; + %group = nameToID("MissionCleanup/Deployables"); + %count = %group.getCount(); + for(%i=0;%i<%count;%i++) { + %obj = %group.getObject(%i); + if (isObject(%obj)) { + if (%obj.getDataBlock().className $= "Generator" && %obj.deployed && !%obj.isRemoved) { + // Not using listAdd() here, for speed + $PowerList = $PowerList SPC %obj; + } + } + } + $PowerList = trim($PowerList); +} + +function globalPowerCheck() { + buildPowerList(); + %group = nameToID("MissionCleanup/Deployables"); + %count = %group.getCount(); + for(%i=0;%i<%count;%i++) { + %obj = %group.getObject(%i); + %obj.powerCount = ""; + if (%obj.getDataBlock().needsPower) + %obj.getDataBlock().losePower(%obj); + checkPowerObject(%obj); + } +} + +function checkPowerGenerator(%powerObj,%stateChange) { + %group = nameToID("MissionCleanup/Deployables"); + %count = %group.getCount(); + for(%i=0;%i<%count;%i++) { + %obj = %group.getObject(%i); + if (%obj.getDataBlock().needsPower) { + if (genLinkedObj(%powerObj,%obj)) { + %obj.powerCount = %obj.powerCount + %stateChange; + checkPowerObject(%obj); + } + } + } +} + +function checkPowerObject(%obj) { + if (%obj.getDataBlock().needsPower) { + %powerCount = %obj.powerCount; + if (%powerCount $= "") { + %count = getWordCount($PowerList); + %powerCount = 0; + for(%i=0;%i<%count;%i++) { + %powerObj = getWord($PowerList,%i); + if (genPoweringObj(%powerObj,%obj)) + %powerCount++; + } + } + %obj.powerCount = %powerCount; + doObjectPower(%obj); + } +} + +function genPoweringObj(%powerObj,%obj) { + %isPowering = false; + if (isObject(%powerObj)){ + if (%powerObj.isEnabled() && %powerObj.isPowered()) { + if (genLinkedObj(%powerObj,%obj)) + %isPowering = true; + } + } + return %isPowering; +} + +function genLinkedObj(%powerObj,%obj) { + if (%obj.powerFreq == %powerObj.powerFreq) { + if (vectorDist(%obj.getPosition(),%powerObj.getPosition()) < %powerObj.getDataBlock().powerRadius + && (%obj.team == %powerObj.team || %powerObj.team == 0) + && !%obj.isRemoved && !%powerObj.isRemoved) { + %lsLinked = true; + } + } + return %lsLinked; +} + +function doObjectPower(%obj) { + if (%obj.powerCount > 0) + %obj.getDataBlock().gainPower(%obj); + else + %obj.getDataBlock().losePower(%obj); +} + +function delNonPoweredPieces(%quiet) { + %randomTime = 10000; + %group = nameToID("MissionCleanup/Deployables"); + %count = %group.getCount(); + for(%i=0;%i<%count;%i++) { + %obj = %group.getObject(%i); + if (%obj.getDataBlock().className !$= "Generator") { + %hasPower = ""; + %count2 = getWordCount($PowerList); + for(%i2=0;%i2<%count2;%i2++) { + %powerObj = getWord($PowerList,%i2); + if (vectorDist(%obj.getPosition(),%powerObj.getPosition()) < %powerObj.getDataBlock().powerRadius) { + %hasPower = true; + break; + } + + } + if (!%hasPower) { + if (!%quiet) + warn("Deleting: " @ %obj @ " Name: " @ %obj.getDataBlock().getName()); + %random = getRandom() * %randomTime; + %obj.getDataBlock().schedule(%random,"disassemble",%plyr,%obj); // Run Item Specific code. + %deleted++; + } + else + %checked++; + } + } + if (!%quiet) { + warn("Checked pieces: " @ %checked); + warn("Deleted pieces: " @ %deleted); + } + return %randomTime; +} + +function displayPowerFreq(%obj) { + %powerFreq = %obj.powerFreq; + if (%powerFreq < 1 || %powerFreq > upperPowerFreq(%obj) || !%powerFreq) + %powerFreq = 1; + %obj.powerFreq = %powerFreq; + bottomPrint(%obj.client,"Your power frequency is set to: " @ %obj.powerFreq,2,1); +} + +function toggleGenerator(%obj,%state) { + if (!isObject(%obj)) + return -1; + %dataBlockName = %obj.getDataBlock().getName(); + if (%dataBlockName $= "GeneratorLarge") { + %switchDelay = 5000; + %displayName = "Generator"; + %powerOnSound = BasePowerOn; + %powerOffSound = BasePowerOff; + } + else if (%dataBlockName $= "SolarPanel") { + %switchDelay = 1000; + %displayName = "Solar Panel"; + %powerOnSound = PlasmaSwitchSound; + %powerOffSound = PlasmaReloadSound; + } + %taggedDisplayName = addTaggedString(%displayName); + if (!%obj.isEnabled()) + return -2 SPC %taggedDisplayName; + if (!(%obj.switchTime + %switchDelay < getSimTime())) + return -3 SPC %taggedDisplayName SPC %obj.switchTime + %switchDelay - getSimTime(); + if (%obj.isSwitchedOff && (%state != false || %state $= "")) { + %obj.isSwitchedOff = ""; + %obj.getDataBlock().gainPower(%obj); + %obj.play3D(%powerOnSound); + setTargetName(%obj.target,addTaggedString("Frequency" SPC %obj.powerFreq)); + %obj.switchTime = getSimTime(); + return 2 SPC %taggedDisplayName; + } + else if (!%obj.isSwitchedOff && (%state != true || %state $= "")) { + %obj.getDataBlock().losePower(%obj); + %obj.isSwitchedOff = 1; + %obj.play3D(%powerOffSound); + setTargetName(%obj.target,addTaggedString("Disabled Frequency" SPC %obj.powerFreq)); + %obj.switchTime = getSimTime(); + return 1 SPC %taggedDisplayName; + } + return 0; +} + +function upperPowerFreq(%plyr) { + if (%plyr.client.isAdmin || %plyr.client.isSuperAdmin) + return 50; + else + return 40; +} diff --git a/scripts/prison.cs b/scripts/prison.cs new file mode 100644 index 0000000..aebe256 --- /dev/null +++ b/scripts/prison.cs @@ -0,0 +1,310 @@ +// prison.cs + +// Set up defaults for nonexisting vars +if ($Host::Prison::Enabled $= "") + $Host::Prison::Enabled = 1; // Enable prison system +if ($Host::Prison::JailMode $= "") + $Host::Prison::JailMode = 0; // Jailing mode + // 0 = prison building + // 1 = spawnsphere + // 2 = players current/last position (prison only affects use of items) +if ($Host::Prison::ReleaseMode $= "") + $Host::Prison::ReleaseMode = 1; // Release mode - same as above + +// Killing +if ($Host::Prison::Kill $= "") + $Host::Prison::Kill = 0; // Enable killing punishment +if ($Host::Prison::TeamKill $= "") + $Host::Prison::TeamKill = 1; // Enable teamkill punishment +if ($Host::Prison::KillTime $= "") + $Host::Prison::KillTime = 2 * 60; // Time to punish for killing/teamkilling + +// Deployables spamming +if ($Host::Prison::DeploySpam $= "") + $Host::Prison::DeploySpam = 1; // Enable deployables spam punishment +if ($Host::Prison::DeploySpamTime $= "") + $Host::Prison::DeploySpamTime = 60; // Time to punish for deployables spamming +if ($Host::Prison::DeploySpamMultiply $= "") + $Host::Prison::DeploySpamMultiply = 1; // Enable punishment multiplier for repeat offenders +if ($Host::Prison::DeploySpamMaxTime $= "") + $Host::Prison::DeploySpamMaxTime = 5 * 60; // Max time, if applying multiplier, to jail a player +if ($Host::Prison::DeploySpamCheckTimeMS $= "") + $Host::Prison::DeploySpamCheckTimeMS = 1000; // Time in MS between deploying that is considered spam +if ($Host::Prison::DeploySpamWarnings $= "") + $Host::Prison::DeploySpamWarnings = 10; // Number of warnings before punishment + // This is a bit misleading. It is actually the number of spams + // allowed before punishment. Warnings will be given for the last + // half of them +if ($Host::Prison::DeploySpamResetWarnCountTime $= "") + $Host::Prison::DeploySpamResetWarnCountTime = 30; // Reset warn counter after this many seconds of not deploying +if ($Host::Prison::DeploySpamRemoveRecentMS $= "") + $Host::Prison::DeploySpamRemoveRecentMS = 1000 * 15; // Remove pieces deployed by offender within the last 15 seconds + +if ($Prison::RemoveSpamTimer < 10000) // Remove spam around prison every 30 seconds, 10 seconds minimum + $Prison::RemoveSpamTimer = 30000; + +function jailPlayer(%cl,%release,%prisonTimeInSeconds,%jailThread) { + %cl.jailThread++; + if (!isObject(%cl)) { + warn("-jailPlayer- no client: " @ %cl @ " (" @ (%release ? "release" : "jail") @ ")"); + return; + } + if (%release) { + if (%jailThread == 0 || %cl.jailThread - 1 == %jailThread) { + %cl.isJailed = false; + if (($Host::Prison::ReleaseMode $= "0" || $Host::Prison::ReleaseMode $= "") + && $Prison::ReleasePos !$= "0" && $Prison::ReleasePos !$= "") { + %cl.player.setVelocity("0 0 0"); + if ($Prison::ReleaseRad > 0) { + %pi = 3.1415926535897932384626433832795; // Whoa.. + %vec = getRandom() * %pi * 2; + %rad = getRandom() * $Prison::ReleaseRad; + %x = %x + (mSin(%vec) * %rad); + %y = %y + (mCos(%vec) * %rad); + %cl.player.setPosition(VectorAdd(%x SPC %y SPC 0,$Prison::ReleasePos)); + } + else + %cl.player.setPosition($Prison::ReleasePos); + } + else if ($Host::Prison::ReleaseMode == 1) { + %cl.player.setVelocity("0 0 0"); + %cl.player.setPosition(Game.pickPlayerSpawn(%cl,false)); + } + else { + // Make sure they still get released from prison building + if (($Host::Prison::JailMode $= "0" || $Host::Prison::JailMode $= "") + && $Prison::JailPos !$= "0" && $Prison::JailPos !$= "") { // This could be handled nicer.. + %cl.player.setVelocity("0 0 0"); + %cl.player.setPosition(%cl.preJailPos); +// %cl.player.setVelocity(%cl.preJailVel); + } + // Else, do nothing. Leave player at current position. + } + buyFavorites(%cl); + if (%cl.player.weaponCount > 0) + %cl.player.selectWeaponSlot(0); + if (%jailThread) // Only show for timed releases + messageAll('msgClient','\c2%1 has been released from jail.',%cl.name); + } + return; + } + if ($Host::Prison::Enabled != true) { + warn("-jailPlayer- prison system is disabled."); + return; + } + %cl.isJailed = true; + %cl.jailTime = %prisonTimeInSeconds; + if (isObject(%cl.player)) { + if (%cl.player.getState() !$="Dead") { + if(%cl.player.isMounted()) { + if(%cl.player.vehicleTurret) + %cl.player.vehicleTurret.getDataBlock().playerDismount(%cl.player.vehicleTurret); + else { + %cl.player.getDataBlock().doDismount(%cl.player,true); + %cl.player.mountVehicle = false; + } + } + serverCmdResetControlObject(%cl); + %cl.player.setInventory(EnergyPack,1,1); // Fix Satchel Charge + %cl.player.clearInventory(); + %cl.setWeaponsHudClearAll(); + %cl.player.setArmor("Light"); + Game.dropFlag(%cl.player); + %cl.preJailVel = %cl.player.getVelocity(); + %cl.preJailPos = %cl.player.getPosition(); + // If we have no prison to put them in, we'll let them run around without any weapons.. + if (($Host::Prison::JailMode $= "0" || $Host::Prison::JailMode $= "") + && $Prison::JailPos !$= "0" && $Prison::JailPos !$= "") { + %cl.player.setVelocity("0 0 0"); + if ($Prison::JailRad > 0) { + %pi = 3.1415926535897932384626433832795; // Whoa.. + %vec = getRandom() * %pi * 2; + %rad = getRandom() * $Prison::JailRad; + %x = %x + (mSin(%vec) * %rad); + %y = %y + (mCos(%vec) * %rad); + %cl.player.setPosition(VectorAdd(%x SPC %y SPC 0,$Prison::JailPos)); + } + else + %cl.player.setPosition($Prison::JailPos); + } + else if ($Host::Prison::JailMode == 1) { + %cl.player.setVelocity("0 0 0"); + %cl.player.setPosition(Game.pickPlayerSpawn(%cl,false)); + } + else { + // Do nothing, leave player's current position + } + cancel(%cl.prisonReleaseSched); + if (%prisonTimeInSeconds > 0) + %cl.prisonReleaseSched = schedule(%prisonTimeInSeconds * 1000,0,jailPlayer,%cl,true,0,%cl.jailThread); + } + } +} + +function prisonCreate() { + %prisonBasePos = "0 0 -10000"; + if (isObject(nameToID(PrisonGroup))) + // Note, this does not handle removal of the PhysicalZones + PrisonGroup.delete(); + %group = nameToID(MissionCleanup); + if(%group == -1) + return; + %p = new SimGroup(PrisonGroup) { + providesPower = true; + new InteriorInstance(PrisonMain) { + position = %prisonBasePos; + rotation = "-1 0 0 90"; + scale = "1 1 1"; + interiorFile = "btowra.dif"; + }; + new ForceFieldBare(PrisonFF1) { + position = VectorAdd("-6.3 -22.5 -2.25",%prisonBasePos); + rotation = "1 0 0 0"; + scale = "12.9 0.18 8.5"; + dataBlock = "defaultSolidFieldBare"; + }; + new ForceFieldBare(PrisonFF2) { + position = VectorAdd("-2.25 -2.25 6.2",%prisonBasePos); + rotation = "1 0 0 0"; + scale = "4.5 4.5 0.18"; + dataBlock = "defaultSolidFieldBare"; + }; + }; + %group.add(%p); + PrisonGroup.powerInit(0); + addPrisonCamera(VectorAdd("0 2 0.5",%prisonBasePos),getWords(MatrixCreateFromEuler(mDegToRad(90)) SPC "0 0",3,6),0); + addPrisonCamera(VectorAdd("1 2 0.5",%prisonBasePos),getWords(MatrixCreateFromEuler(mDegToRad(90)) SPC "0 0",3,6),1); + addPrisonCamera(VectorAdd("-1 2 0.5",%prisonBasePos),getWords(MatrixCreateFromEuler(mDegToRad(90)) SPC "0 0",3,6),2); + $Prison::JailRad = 3; + $Prison::JailPos = VectorAdd("0 -8.5 0",%prisonBasePos); + $Prison::ReleaseRad = 4; + $Prison::ReleasePos = VectorAdd("0 -14.25 6.75",%prisonBasePos); // Release player on top of prison + $Prison::NoBuildRadius = 50; +} + +// Prevent spam in prison. If called outside prisonCreate(), needs to be passed $Prison::RemoveSpamThread++ as arg +function prisonRemoveSpamThread(%thread) { + // Re-evaluate here, in case user has set it to an "illegal" value + if ($Prison::RemoveSpamTimer < 10000) // 10 seconds + $Prison::RemoveSpamTimer = 10000; + // Thread cancels if prison is re-created, if PrisonGroup ceases to exist, or if prison system is disabled + if (%thread != $Prison::RemoveSpamThread || !isObject(nameToID(PrisonGroup)) || $Host::Prison::Enabled != 1) { + warn("prisonRemoveSpamThread #" @ mAbs(%thread) @ " stopped. Last started thread: " @ $Prison::RemoveSpamThread); + return; + } + InitContainerRadiusSearch($Prison::JailPos,$Prison::NoBuildRadius,$TypeMasks::StaticShapeObjectType | $TypeMasks::ItemObjectType | $TypeMasks::ForceFieldObjectType); + while((%obj = ContainerSearchNext()) != 0) { + // Extra safety + if (VectorDist($Prison::JailPos,%obj.getPosition()) < $Prison::NoBuildRadius) { + %dataBlockName = %obj.getDataBlock().getName(); + if (saveBuildingCheck(%obj)) { // If it's handled by saveBuilding(), it must be a deployable + %random = getRandom() * $Prison::RemoveSpamTimer-2000; // prevent duplicate disassemblies + %obj.getDataBlock().schedule(%random,"disassemble",0,%obj); // Run Item Specific code. + } + } + } + schedule($Prison::RemoveSpamTimer,0,prisonRemoveSpamThread,%thread); +} + +function prisonEnable() { + $Host::Prison::Enabled = 1; + %pgroup = nameToID(PrisonGroup); + if(isObject(%pgroup)) { + %pgroup.providesPower = true; + %pgroup.powerInit(0); + } + else + prisonCreate(); + prisonRemoveSpamThread($Prison::RemoveSpamThread++); +} + +function prisonDisable() { + $Host::Prison::Enabled = 0; + %pgroup = nameToID(PrisonGroup); + if(isObject(%pgroup)) { + %pgroup.providesPower = false; + %pgroup.powerInit(0); + } + // Release jailed players + %count = ClientGroup.getCount(); + for(%i = 0; %i < %count; %i++) { + %cl = ClientGroup.getObject(%i); + if (%cl.isJailed) + jailPlayer(%cl,true); + } +} + +datablock SensorData(PrisonCameraSensorObject) { + detects = false; +}; + +datablock TurretData(TurretPrisonCamera) { + className = PrisonCameraTurret; + shapeFile = "camera.dts"; + + thetaMin = 50; + thetaMax = 130; +// thetaNull = 90; + + cameraDefaultFov = 120; + cameraMinFov = 120; + cameraMaxFov = 120; + + neverUpdateControl = false; + + canControl = true; + canObserve = true; + observeThroughObject = true; + cmdCategory = "Support"; + cmdIcon = CMDCameraIcon; + cmdMiniIconName = "commander/MiniIcons/com_camera_grey"; + targetNameTag = 'Prison'; + targetTypeTag = 'Camera'; + sensorData = PrisonCameraSensorObject; + sensorRadius = PrisonCameraSensorObject.detectRadius; + + firstPersonOnly = true; + observeParameters = "0.5 4.5 4.5"; +}; + +datablock TurretImageData(PrisonCameraBarrel) { + shapeFile = "turret_muzzlepoint.dts"; + usesEnergy = false; + + // Turret parameters + activationMS = 100; + deactivateDelayMS = 100; + thinkTimeMS = 100; + degPerSecTheta = 180; + degPerSecPhi = 360; +}; + +function addPrisonCamera(%pos,%rot,%team) { + %group = nameToID(PrisonGroup); + if (!isObject(%group)) + return; + %pCam = new Turret(PrisonCamera) { + dataBlock = "TurretPrisonCamera"; + position = %pos; + rotation = %rot; + team = %team; + needsNoPower = true; + }; + %pCam.setRotation(%rot); // Gah! + %group.add(%pCam); + + if(%pCam.getTarget() != -1) + setTargetSensorGroup(%pCam.getTarget(),%team); + %pCam.deploy(); +} + +function TurretPrisonCamera::damageObject(%data,%targetObject,%sourceObject,%position,%amount,%damageType,%momVec,%mineSC) { + // Do nothing +} + +function TurretPrisonCamera::onAdd(%this, %obj) { + Parent::onAdd(%this, %obj); + %obj.mountImage(PrisonCameraBarrel, 0, true); + %obj.setRechargeRate(%this.rechargeRate); + %obj.setAutoFire(false); // z0ddm0d: Server crash fix related to controlable cameras +} diff --git a/scripts/projectiles.cs b/scripts/projectiles.cs new file mode 100644 index 0000000..654f4fd --- /dev/null +++ b/scripts/projectiles.cs @@ -0,0 +1,683 @@ +//-------------------------------------------------------------------------- +// Projectiles.cs: Note that the actual projectile blocks are stored with +// with weapon that uses them in base/scripts/weapons/*.cs, +// the blocks below are only to illustrate the default values +// for each block type. Also, ProjectileData cannot be used +// as a concrete datablock type. +// Inheritance: +// ProjectileData : GameBaseData +// LinearProjectileData : ProjectileData +// LinearFlareProjectileData : LinearProjectileData +// GrenadeProjectileData : ProjectileData +// SeekerProjectileData : ProjectileData +// SniperProjectileData : ProjectileData +// +//-------------------------------------------------------------------------- +//-------------------------------------- Default functions +// +function ProjectileData::onCollision(%data, %projectile, %targetObject, %modifier, %position, %normal) +{ + if(isObject(%targetObject)) // Console spam fix - ToS. z0ddm0d + { + %targetObject.damage(%projectile.sourceObject, %position, %data.directDamage * %modifier, %data.directDamageType); + } +} + +function SniperProjectileData::onCollision(%data, %projectile, %targetObject, %modifier, %position, %normal) +{ + %damageAmount = %data.directDamage * %projectile.damageFactor; + + if(isObject(%targetObject)) // Console spam fix - ToS. z0ddm0d + { + if(%targetObject.getDataBlock().getClassName() $= "PlayerData") + { + %damLoc = firstWord(%targetObject.getDamageLocation(%position)); + if(%damLoc $= "head") + { + %targetObject.getOwnerClient().headShot = 1; + %modifier = %data.rifleHeadMultiplier; + } + else + { + %modifier = 1; + %targetObject.getOwnerClient().headShot = 0; + } + } + %targetObject.damage(%projectile.sourceObject, %position, %modifier * %damageAmount, %data.directDamageType); + } +} + +function ShapeBaseImageData::onFire(%data, %obj, %slot) +{ + %data.lightStart = getSimTime(); + + if( %obj.station $= "" && %obj.isCloaked() ) + { + if( %obj.respawnCloakThread !$= "" ) + { + Cancel(%obj.respawnCloakThread); + %obj.setCloaked( false ); + %obj.respawnCloakThread = ""; + } + else + { + if( %obj.getEnergyLevel() > 20 ) + { + %obj.setCloaked( false ); + %obj.reCloak = %obj.schedule( 500, "setCloaked", true ); + } + } + } + + if( %obj.client > 0 ) + { + %obj.setInvincibleMode(0 ,0.00); + %obj.setInvincible( false ); // fire your weapon and your invincibility goes away. + } + + %vehicle = 0; + if(%data.usesEnergy) + { + if(%data.useMountEnergy) + { + %useEnergyObj = %obj.getObjectMount(); + if(!%useEnergyObj) + %useEnergyObj = %obj; + %energy = %useEnergyObj.getEnergyLevel(); + %vehicle = %useEnergyObj; + } + else + %energy = %obj.getEnergyLevel(); + + if(%data.useCapacitor && %data.usesEnergy) + { + if( %useEnergyObj.turretObject.getCapacitorLevel() < %data.minEnergy ) + { + return; + } + } + else if(%energy < %data.minEnergy) + return; + } + // --------------------------------------------------------------------- + // Code streamlining - ToS. z0ddm0d + if(%data.projectileSpread) + { + %vec = %obj.getMuzzleVector(%slot); + %x = (getRandom() - 0.5) * 2 * 3.1415926 * %data.projectileSpread; + %y = (getRandom() - 0.5) * 2 * 3.1415926 * %data.projectileSpread; + %z = (getRandom() - 0.5) * 2 * 3.1415926 * %data.projectileSpread; + %mat = MatrixCreateFromEuler(%x @ " " @ %y @ " " @ %z); + %vector = MatrixMulVector(%mat, %vec); + } + else + { + %vector = %obj.getMuzzleVector(%slot); + } + %initialPos = %obj.getMuzzlePoint(%slot); + if (%data.muzzleSlots) { + %nrm = %vector; + %nrm2 = vectorNormalize(vectorCross("0 0 -1",%nrm)); + %nrm3 = vectorNormalize(vectorCross(%nrm2,%nrm)); + %offsetVec = %data.muzzleSlotOffset[%obj.currentMuzzleSlot]; + + %initialPos = vectorAdd(%initialPos,vectorScale(%nrm2,getWord(%offsetVec,0))); + %initialPos = vectorAdd(%initialPos,vectorScale(%nrm,getWord(%offsetVec,1))); + %initialPos = vectorAdd(%initialPos,vectorScale(%nrm3,getWord(%offsetVec,2))); + %obj.currentMuzzleSlot++; + if (%obj.currentMuzzleSlot > %data.muzzleSlots - 1) + %obj.currentMuzzleSlot = 0; + } + + %p = new (%data.projectileType)() { + dataBlock = %data.projectile; + initialDirection = %vector; + initialPosition = %initialPos; + sourceObject = %obj; + sourceSlot = %slot; + vehicleObject = %vehicle; + }; + // End streamlining + // --------------------------------------------------------------------- + if (isObject(%obj.lastProjectile) && %obj.deleteLastProjectile) + %obj.lastProjectile.delete(); + + %obj.lastProjectile = %p; + %obj.deleteLastProjectile = %data.deleteLastProjectile; + MissionCleanup.add(%p); + + // AI hook + if(%obj.client) + %obj.client.projectile = %p; + + if(%data.usesEnergy) + { + if(%data.useMountEnergy) + { + if( %data.useCapacitor ) + { + %vehicle.turretObject.setCapacitorLevel( %vehicle.turretObject.getCapacitorLevel() - %data.fireEnergy ); + } + else + %useEnergyObj.setEnergyLevel(%energy - %data.fireEnergy); + } + else + %obj.setEnergyLevel(%energy - %data.fireEnergy); + } + else + %obj.decInventory(%data.ammo,1); + return %p; +} + +function ShapeBaseImageData::onUnmount(%data, %obj, %slot) +{ + if (%data.deleteLastProjectile && isObject(%obj.lastProjectile)) + { + %obj.lastProjectile.delete(); + %obj.lastProjectile = ""; + } +} + +function TurretImageData::deconstruct(%data, %obj, %slot) +{ + if (%data.deleteLastProjectile && isObject(%obj.lastProjectile)) + { + %obj.lastProjectile.delete(); + %obj.lastProjectile = ""; + } +} + +function ShapeBaseImageData::deconstruct(%data, %obj, %slot) +{ + if (%data.deleteLastProjectile && isObject(%obj.lastProjectile)) + { + %obj.lastProjectile.delete(); + %obj.lastProjectile = ""; + } +} + +function MissileLauncherImage::onFire(%data,%obj,%slot) +{ + %p = Parent::onFire(%data, %obj, %slot); + MissileSet.add(%p); + + %target = %obj.getLockedTarget(); + if(%target) + %p.setObjectTarget(%target); + else if(%obj.isLocked()) + %p.setPositionTarget(%obj.getLockedPosition()); + else + %p.setNoTarget(); +} + +function MissileLauncherImage::onWetFire(%data, %obj, %slot) +{ + %p = Parent::onFire(%data, %obj, %slot); + MissileSet.add(%p); + + %p.setObjectTarget(0); +} + +//-------------------------------------------------------------------------- + +function MissileBarrelLarge::onFire(%data,%obj,%slot) +{ + %p = Parent::onFire(%data,%obj,%slot); + + if (%obj.getControllingClient()) + { + // a player is controlling the turret + %target = %obj.getLockedTarget(); + } + else + { + // The ai is controlling the turret + %target = %obj.getTargetObject(); + } + + if(%target) + %p.setObjectTarget(%target); + else if(%obj.isLocked()) + %p.setPositionTarget(%obj.getLockedPosition()); + else + %p.setNoTarget(); // set as unguided. Only happens when itchy trigger can't wait for lock tone. +} + +//add mortars to the "grenade set" so the AI's can avoid them better... +function MortarImage::onFire(%data,%obj,%slot) +{ + %p = Parent::onFire(%data, %obj, %slot); + AIGrenadeThrown(%p); +} + +function SniperRifleImage::onFire(%data,%obj,%slot) +{ + if(!%obj.hasEnergyPack) + { + // siddown Junior, you can't use it + serverPlay3D(SniperRifleDryFireSound, %obj.getTransform()); + return; + } + + %pct = %obj.getEnergyLevel() / %obj.getDataBlock().maxEnergy; + %p = new (%data.projectileType)() { + dataBlock = %data.projectile; + initialDirection = %obj.getMuzzleVector(%slot); + initialPosition = %obj.getMuzzlePoint(%slot); + sourceObject = %obj; + damageFactor = %pct * %pct; + sourceSlot = %slot; + }; + %p.setEnergyPercentage(%pct); + + %obj.lastProjectile = %p; + MissionCleanup.add(%p); + serverPlay3D(SniperRifleFireSound, %obj.getTransform()); + + // AI hook + if(%obj.client) + %obj.client.projectile = %p; + + %obj.setEnergyLevel(0); +} + +function ElfGunImage::onFire(%data, %obj, %slot) +{ + %p = Parent::onFire(%data, %obj, %slot); + + if(!%p.hasTarget()) + %obj.playAudio(0, ELFFireWetSound); +} + +function TargetingLaserImage::onFire(%data,%obj,%slot) +{ + %p = Parent::onFire(%data, %obj, %slot); + %p.setTarget(%obj.team); + %obj.posLaze = 1; +} + +function TargetingLaserImage::deconstruct(%data, %obj, %slot) +{ + %obj.posLaze = 0; + Parent::deconstruct(%data, %obj, %slot); +} + +function ShockLanceImage::onFire(%this, %obj, %slot) +{ + if( %obj.isCloaked() ) + { + if( %obj.respawnCloakThread !$= "" ) + { + Cancel(%obj.respawnCloakThread); + %obj.setCloaked( false ); + } + else + { + if( %obj.getEnergyLevel() > 20 ) + { + %obj.setCloaked( false ); + %obj.reCloak = %obj.schedule( 500, "setCloaked", true ); + } + } + } + + %muzzlePos = %obj.getMuzzlePoint(%slot); + %muzzleVec = %obj.getMuzzleVector(%slot); + + %endPos = VectorAdd(%muzzlePos, VectorScale(%muzzleVec, %this.projectile.extension)); + + %damageMasks = $TypeMasks::PlayerObjectType | $TypeMasks::VehicleObjectType | + $TypeMasks::StationObjectType | $TypeMasks::GeneratorObjectType | + $TypeMasks::SensorObjectType | $TypeMasks::TurretObjectType; + + %everythingElseMask = $TypeMasks::TerrainObjectType | + $TypeMasks::InteriorObjectType | + $TypeMasks::ForceFieldObjectType | + $TypeMasks::StaticObjectType | + $TypeMasks::MoveableObjectType | + $TypeMasks::DamagableItemObjectType; + + // did I miss anything? players, vehicles, stations, gens, sensors, turrets + %hit = ContainerRayCast(%muzzlePos, %endPos, %damageMasks | %everythingElseMask, %obj); + + %noDisplay = true; + + if (%hit !$= "0") + { + %obj.setEnergyLevel(%obj.getEnergyLevel() - %this.hitEnergy); + + %hitobj = getWord(%hit, 0); + %hitpos = getWord(%hit, 1) @ " " @ getWord(%hit, 2) @ " " @ getWord(%hit, 3); + + if ( %hitObj.getType() & %damageMasks ) + { + %hitobj.applyImpulse(%hitpos, VectorScale(%muzzleVec, %this.projectile.impulse)); + %obj.playAudio(0, ShockLanceHitSound); + + // This is truly lame, but we need the sourceobject property present... + %p = new ShockLanceProjectile() { + dataBlock = %this.projectile; + initialDirection = %obj.getMuzzleVector(%slot); + initialPosition = %obj.getMuzzlePoint(%slot); + sourceObject = %obj; + sourceSlot = %slot; + targetId = %hit; + }; + MissionCleanup.add(%p); + + %damageMultiplier = 1.0; + + if(%hitObj.getDataBlock().getClassName() $= "PlayerData") + { + // Now we see if we hit from behind... + %forwardVec = %hitobj.getForwardVector(); + %objDir2D = getWord(%forwardVec, 0) @ " " @ getWord(%forwardVec,1) @ " " @ "0.0"; + %objPos = %hitObj.getPosition(); + %dif = VectorSub(%objPos, %muzzlePos); + %dif = getWord(%dif, 0) @ " " @ getWord(%dif, 1) @ " 0"; + %dif = VectorNormalize(%dif); + %dot = VectorDot(%dif, %objDir2D); + + // 120 Deg angle test... + // 1.05 == 60 degrees in radians + if (%dot >= mCos(1.05)) { + // Rear hit + %damageMultiplier = 3.0; + } + } + + %totalDamage = %this.Projectile.DirectDamage * %damageMultiplier; + %hitObj.getDataBlock().damageObject(%hitobj, %p.sourceObject, %hitpos, %totalDamage, $DamageType::ShockLance); + + %noDisplay = false; + } + } + + if( %noDisplay ) + { + // Miss + %obj.setEnergyLevel(%obj.getEnergyLevel() - %this.missEnergy); + %obj.playAudio(0, ShockLanceMissSound); + + %p = new ShockLanceProjectile() { + dataBlock = %this.projectile; + initialDirection = %obj.getMuzzleVector(%slot); + initialPosition = %obj.getMuzzlePoint(%slot); + sourceObject = %obj; + sourceSlot = %slot; + }; + MissionCleanup.add(%p); + + } +} + +$ELFZapSound = 2; +$ELFFireSound = 3; + +function ELFProjectileData::zapTarget(%data, %projectile, %target, %targeter) +{ + %oldERate = %target.getRechargeRate(); + %target.teamDamageStateOnZap = $teamDamage; + %teammates = %target.client.team == %targeter.client.team; + + if( %target.teamDamageStateOnZap || !%teammates ) + %target.setRechargeRate(%oldERate - %data.drainEnergy); + else + %target.setRechargeRate(%oldERate); + + %projectile.checkELFStatus(%data, %target, %targeter); +} + +function ELFProjectileData::unzapTarget(%data, %projectile, %target, %targeter) +{ + cancel(%projectile.ELFrecur); + %target.stopAudio($ELFZapSound); + %targeter.stopAudio($ELFFireSound); + %target.zapSound = false; + %targeter.zappingSound = false; + %teammates = %target.client.team == %targeter.client.team; + + if(!%target.isDestroyed()) + { + %oldERate = %target.getRechargeRate(); + if( %target.teamDamageStateOnZap || !%teammates ) + %target.setRechargeRate(%oldERate + %data.drainEnergy); + else + %target.setRechargeRate(%oldERate); + } +} + +function ELFProjectileData::targetDestroyedCancel(%data, %projectile, %target, %targeter) +{ + cancel(%projectile.ELFrecur); + %target.stopAudio($ELFZapSound); + %targeter.stopAudio($ELFFireSound); + %target.zapSound = false; + %targeter.zappingSound = false; + %projectile.delete(); +} + +function ELFProjectile::checkELFStatus(%this, %data, %target, %targeter) +{ + if(isObject(%target)) + { + if(%target.getDamageState() $= "Destroyed") + { + %data.targetDestroyedCancel(%this, %target, %targeter); + return; + } + + %enLevel = %target.getEnergyLevel(); + if(%enLevel < 1.0) + { + %dataBlock = %target.getDataBlock(); + %dataBlock.damageObject(%target, %this.sourceObject, %target.getPosition(), %data.drainHealth, %data.directDamageType); + + } + else + { + %normal = "0.0 0.0 1.0"; + %target.playShieldEffect( %normal ); + } + %this.ELFrecur = %this.schedule(32, checkELFStatus, %data, %target, %targeter); + + %targeter.playAudio($ELFFireSound, ELFGunFireSound); + if(!%target.zapSound) + { + %target.playAudio($ELFZapSound, ELFHitTargetSound); + %target.zapSound = true; + %targeter.zappingSound = true; + } + } + // ------------------------------------------------------- + // z0dd - ZOD, 5/27/02. Stop firing if there is no target, + // fixes continuous fire bug. + //else if(%targeter.zappingSound) + //{ + // %targeter.stopAudio($ELFFireSound); + // %targeter.zappingSound = false; + //} + else + { + if(%targeter.zappingSound) + { + %targeter.stopAudio($ELFFireSound); + %targeter.zappingSound = false; + } + %data.targetDestroyedCancel(%this, %target, %targeter); + return; + } + // End z0dd - ZOD + // ------------------------------------------------------- +} + + +function RadiusExplosion(%explosionSource, %position, %radius, %damage, %impulse, %sourceObject, %damageType) +{ + InitContainerRadiusSearch(%position, %radius, $TypeMasks::PlayerObjectType | + $TypeMasks::VehicleObjectType | + $TypeMasks::StaticShapeObjectType | + $TypeMasks::TurretObjectType | + $TypeMasks::ForceFieldObjectType | + $TypeMasks::ItemObjectType); + + %numTargets = 0; + while ((%targetObject = containerSearchNext()) != 0) + { + + if (%targetObject.isRemoved) + continue; + + %dist = containerSearchCurrRadDamageDist(); + + if (%dist > %radius) + continue; + + if (!(%targetObject.getType() & $TypeMasks::ForceFieldObjectType)) { + if (%targetObject.isMounted()) { + %mount = %targetObject.getObjectMount(); + %found = -1; + for (%i = 0; %i < %mount.getDataBlock().numMountPoints; %i++) { + if (%mount.getMountNodeObject(%i) == %targetObject) { + %found = %i; + break; + } + } + + if (%found != -1) { + if (%mount.getDataBlock().isProtectedMountPoint[%found]) { + continue; + } + } + } + } + %targets[%numTargets] = %targetObject; + %targetDists[%numTargets] = %dist; + %numTargets++; + } + + for (%i = 0; %i < %numTargets; %i++) + { + %targetObject = %targets[%i]; + %dist = %targetDists[%i]; + + %coverage = calcExplosionCoverage(%position, %targetObject, + ($TypeMasks::InteriorObjectType | + $TypeMasks::TerrainObjectType | + $TypeMasks::ForceFieldObjectType | + $TypeMasks::VehicleObjectType)); + if (%coverage == 1) + %coverage = calcBuildingInWay(%position, %targetObject); + if (%coverage == 0) + continue; + + //if ( $splashTest ) + %amount = (1.0 - ((%dist / %radius) * 0.88)) * %coverage * %damage; + //else + //%amount = (1.0 - (%dist / %radius)) * %coverage * %damage; + + //error( "damage: " @ %amount @ " at distance: " @ %dist @ " radius: " @ %radius @ " maxDamage: " @ %damage ); + + %data = %targetObject.getDataBlock(); + %className = %data.className; + + if (%impulse && %data.shouldApplyImpulse(%targetObject)) + { + %p = %targetObject.getWorldBoxCenter(); + %momVec = VectorSub(%p, %position); + %momVec = VectorNormalize(%momVec); + %impulseVec = VectorScale(%momVec, %impulse * (1.0 - (%dist / %radius))); + %doImpulse = true; + } + // --------------------------------------------------------------------------- + // z0dd - ZOD, 5/8/02. Removed Wheeled Vehicle to eliminate the flying MPB bug + // caused by tossing concussion grenades under a deployed MPB. + //else if( %className $= WheeledVehicleData || %className $= FlyingVehicleData || %className $= HoverVehicleData ) + else if( %className $= FlyingVehicleData || %className $= HoverVehicleData ) + { + %p = %targetObject.getWorldBoxCenter(); + %momVec = VectorSub(%p, %position); + %momVec = VectorNormalize(%momVec); + + %impulseVec = VectorScale(%momVec, %impulse * (1.0 - (%dist / %radius))); + + if( getWord( %momVec, 2 ) < -0.5 ) + %momVec = "0 0 1"; + + // Add obj's velocity into the momentum vector + %velocity = %targetObject.getVelocity(); + //%momVec = VectorNormalize( vectorAdd( %momVec, %velocity) ); + %doImpulse = true; + } + else + { + %momVec = "0 0 1"; + %doImpulse = false; + } + + if(%amount > 0) + %data.damageObject(%targetObject, %sourceObject, %position, %amount, %damageType, %momVec, %explosionSource.theClient, %explosionSource); + else if( %explosionSource.getDataBlock().getName() $= "ConcussionGrenadeThrown" && %data.getClassName() $= "PlayerData" ) { + %data.applyConcussion( %dist, %radius, %sourceObject, %targetObject ); + if(!$teamDamage && %sourceObject != %targetObject && %sourceObject.client.team == %targetObject.client.team) + messageClient(%targetObject.client, 'msgTeamConcussionGrenade', '\c1You were hit by %1\'s concussion grenade.', getTaggedString(%sourceObject.client.name)); + } + + if(%doImpulse) + %targetObject.applyImpulse(%position, %impulseVec); + } +} + +function ProjectileData::onExplode(%data, %proj, %pos, %mod) +{ + if (%data.hasDamageRadius) + RadiusExplosion(%proj, %pos, %data.damageRadius, %data.indirectDamage, %data.kickBackStrength, %proj.sourceObject, %data.radiusDamageType); +} + +function Flag::shouldApplyImpulse(%data, %obj) +{ + if(%obj.isHome) + return false; + else + return true; +} + +// TODO - update +function calcBuildingInWay(%position, %targetObject) { + %targetPos = posFromTransform(%targetObject.getWorldBoxCenter()); +// %vec = vectorNormalize(vectorSub(%position,%targetPos)); +// %sourcePos = vectorAdd(%position,vectorScale(%vec,0.125)); + %sourcePos = %position; + %mask = $TypeMasks::StaticObjectType; + %found = containerRayCast(%sourcePos, %targetPos, %mask); + if (%found) { + if ((%found.getClassName() $= InteriorInstance) || (%found.getClassName() $= TerrainBlock) || (%found.getClassName() $= TSStatic)) + return 1; + if (%found == %targetObject) + return 1; + if (%found.getDataBlock().className $= "wall" + || %found.getDataBlock().className $= "wWall" + || %found.getDataBlock().className $= "spine" + || %found.getDataBlock().className $= "mSpine" + || %found.getDataBlock().className $= "floor" + || %found.getDataBlock().className $= "forcefield") + return 0; + else { + %found = containerRayCast(%sourcePos, %targetPos, %mask, %found); + if (%found) { + if ((%found.getClassName() $= InteriorInstance) || (%found.getClassName() $= TerrainBlock) || (%found.getClassName() $= TSStatic)) + return 1; + if (%found == %targetObject) + return 1; + if (%found.getDataBlock().className $= "wall" + || %found.getDataBlock().className $= "wWall" + || %found.getDataBlock().className $= "spine" + || %found.getDataBlock().className $= "mSpine" + || %found.getDataBlock().className $= "floor" + || %found.getDataBlock().className $= "forcefield") + return 0; + } + } + } + return 1; +} diff --git a/scripts/saveBuilding.cs b/scripts/saveBuilding.cs new file mode 100644 index 0000000..c584146 --- /dev/null +++ b/scripts/saveBuilding.cs @@ -0,0 +1,841 @@ +// SaveBuilding.cs +// +// This script made possible by a joint effort of DynaBlade and JackTL +// +// Functions: +// +// saveBuilding(clientId,radius,file[$],quiet[1/0]) +// saveBuildingCentered(clientId,radius,file[$],quiet[1/0],centerAtMinZ[1/0]) +// delBuildingWaypoint() +// loadBuilding(file[$]) +// saveBuildingTimer(time in seconds,globalEcho[1/0],file[$],useMultipleFiles[1/0]) // No limit on multiple files yet. Beware +// saveBuildingTimerOn() // <-- for restarting timed saves, does not initialize like saveBuildingTimer() +// saveBuildingTimerOff() +// delDupPieces(clientId,radius,quiet[1/0]) // NOTE: There are issues with calling this function a second time before the previous call's deconstruction has finished +// +// See functions for (some) comments + +if ($SaveBuilding::SaveFolder $= "") + $SaveBuilding::SaveFolder = "Buildings/"; +if ($SaveBuilding::AutoSaveFolder $= "") + $SaveBuilding::AutoSaveFolder = "Buildings/AutoSave/"; +if ($SaveBuilding::TimerDefaultTime $= "") + $SaveBuilding::TimerDefaultTime = 5 * 60 * 1000; // 5 minutes. Saving may cause stutter on low-end servers with high number of pieces +if ($SaveBuilding::QuickDelete $= "") + $SaveBuilding::QuickDelete = 1; + + +// See if we want to save the piece +function saveBuildingCheck(%obj) { + %save = false; + %dataBlockName = %obj.getDatablock().getName(); + switch$ (%dataBlockName) { + case "DeployedSpine": + %save = true; + case "DeployedWoodSpine": + %save = true; + case "DeployedMSpine": + %save = true; + case "DeployedMSpineRing": + %save = true; + case "DeployedFloor": + %save = true; + case "DeployedWall": + %save = true; + case "DeployedwWall": + %save = true; + case "DeployedEnergizer": + %save = true; + case "DeployedStationInventory": + %save = true; + case "DeployedJumpad": + %save = true; + case "DeployedEscapePod": + %save = true; + case "TelePadDeployedBase": + %save = true; + case "TelePadBeam": + %save = true; + case "DeployedLTarget": + %save = true; + case "DeployedLogoProjector": + %save = true; + case "DeployedSwitch": + %save = true; + case "DeployedPulseSensor": + %save = true; + case "DeployedMotionSensor": + %save = true; + case "TurretDeployedBase": + %save = true; + case "TurretDeployedFloorIndoor": + %save = true; + case "TurretDeployedWallIndoor": + %save = true; + case "TurretDeployedCeilingIndoor": + %save = true; + case "TurretDeployedOutdoor": + %save = true; + case "LaserDeployed": + %save = true; + case "MissileRackTurretDeployed": + %save = true; + case "DiscTurretDeployed": + %save = true; + case "TurretDeployedCamera": + %save = true; + case "DeployedLightBase": + %save = true; + case "DeployedTripwire": + %save = true; + case "DispenserDep": + %save = true; + case "AudioDep": + %save = true; + case "EmitterDep": + %save = true; + } + if (%dataBlockName $= "StationInventory" && %obj.deployed == true) + %save = true; + if (%dataBlockName $= "GeneratorLarge" && %obj.deployed == true) + %save = true; + if (%dataBlockName $= "SolarPanel" && %obj.deployed == true) + %save = true; + if (%dataBlockName $= "SensorMediumPulse" && %obj.deployed == true) + %save = true; + if (%dataBlockName $= "SensorLargePulse" && %obj.deployed == true) + %save = true; + if (getSubStr(%dataBlockName,0,18) $= "DeployedForceField") + %save = true; + if (getSubStr(%dataBlockName,0,20) $= "DeployedGravityField") + %save = true; + if (getSubStr(%dataBlockName,0,12) $= "DeployedTree") + %save = true; + if (getSubStr(%dataBlockName,0,13) $= "DeployedCrate") + %save = true; + if (getSubStr(%dataBlockName,0,18) $= "DeployedDecoration") + %save = true; + return %save; +} + +// This function saves a building and its position in the map +function saveBuilding(%cl,%rad,%file,%quiet,%isAutoSave) { + if (%quiet == true) { + $SaveBuilding::Quiet = true; + } + else { + $SaveBuilding::Quiet = false; // Overwrite + } + %origCl = %cl; + if (!isObject(%cl)) { + if (isObject(nameToID(LocalClientConnection))) { + %cl = nameToID(LocalClientConnection); + } + else { + if ($CurrentClientId) { + %cl = $CurrentClientId; + } + } + } + if (%rad < 1) { + %rad = 100000; + } + %buildingCount = 0; + if (%file $= "" || %file $= "0") { + for(%found = true; %found; %buildingCount++ ) { + %suffix = %buildingCount; + while (strLen(%suffix) < 5) %suffix = "0" @ %suffix; + if (%isAutoSave) + %file = $SaveBuilding::AutoSaveFolder @ $MissionName @ "-" @ %suffix @ ".cs"; + else + %file = $SaveBuilding::SaveFolder @ %cl.nameBase @ "-" @ $MissionName @ "-" @ %suffix @ ".cs"; + %found = isFile(%file); + } + } + else { + if (%isAutoSave) + %file = $SaveBuilding::AutoSaveFolder @ %file; + else + %file = $SaveBuilding::SaveFolder @ %file; + } + if (isObject(%cl.getControlObject())) { + %pos = %cl.getControlObject().getPosition(); + } + if (!%pos) { + %pos = "0 0 0"; + } + if (%isAutoSave && (%origCl $= "" || %origCl $= "0")) + %pos = "0 0 0"; + new fileObject("Building"); + if (!$SaveBuilding::Quiet) { + warn("Saving to file: \"" @ %file @ "\""); + } + Building.openForWrite(%file); + Building.writeLine("// CONSTRUCTION MOD SAVE FILE"); + Building.writeLine("// Saved by \"" @ getField(%cl.nameBase,0) @ "\""); + Building.writeLine("// Created in mission \"" @ $MissionName @ "\""); + Building.writeLine("// Construction " @ $ModVersion); + Building.writeLine(""); + + $SaveBuilding::Saved = 0; + $SaveBuilding::Skipped = 0; + initContainerRadiusSearch(%pos,%rad,$TypeMasks::StaticShapeObjectType | $TypeMasks::ForceFieldObjectType | $TypeMasks::ItemObjectType); + while((%obj = containerSearchNext()) != 0) { + %cmp = writeBuildingComponent(%obj); + if (%cmp !$= "") { + Building.writeLine(%cmp); + } + } + + if (!$SaveBuilding::Quiet) { + warn("Saved to file: \"" @ %file @ "\""); + warn("Saved pieces: " @ $SaveBuilding::Saved); + warn("Skipped pieces: " @ $SaveBuilding::Skipped); + } + + $SaveBuilding::LastFile = %file; + + Building.close(); + Building.delete(); + return %file; +} + +function writeBuildingComponent(%obj) { + %dataBlockName = %obj.getDatablock().getName(); + %save = false; + %save = saveBuildingCheck(%obj); + if (%save == true) { + if (%dataBlockName $= "DeployedMSpineRing") // Handled by DeployedMSpine + return; + if (%dataBlockName $= "TelePadBeam") // Handled by TelePadDeployedBase + return; + if (%dataBlockName $= "DeployedLTarget") // Handled by parent object + return; + if (!$SaveBuilding::Quiet) + echo("Saving: " @ %obj @ " Name: " @ %dataBlockName); + %buildingPiece = "%building = new (" @ %obj.getClassName() @ ") () {"; + %buildingPiece = %buildingPiece @ "datablock = \"" @ %dataBlockName @ "\";"; + if (%obj.position !$= "") %buildingPiece = %buildingPiece @ "position = \"" @ %obj.position @ "\";"; + if (%obj.rotation !$= "") %buildingPiece = %buildingPiece @ "rotation = \"" @ %obj.rotation @ "\";"; + if (%obj.realScale !$= "") %buildingPiece = %buildingPiece @ "scale = \"" @ %obj.realScale @ "\";"; + else {if (%obj.scale !$= "") %buildingPiece = %buildingPiece @ "scale = \"" @ %obj.scale @ "\";";} + if (%obj.team !$= "") %buildingPiece = %buildingPiece @ "team = \"" @ %obj.team @ "\";"; + if (%obj.ownerGUID !$= "") %buildingPiece = %buildingPiece @ "ownerGUID = \"" @ %obj.ownerGUID @ "\";"; + if (%obj.needsFit) %buildingPiece = %buildingPiece @ "needsfit = \"" @ %obj.needsFit @ "\";"; + if (%obj.grounded) %buildingPiece = %buildingPiece @ "grounded = \"" @ %obj.grounded @ "\";"; + if (%obj.deployed !$= "") %buildingPiece = %buildingPiece @ "deployed = \"" @ %obj.deployed @ "\";"; + if (%obj.impulse !$= "") %buildingPiece = %buildingPiece @ "impulse = \"" @ %obj.impulse @ "\";"; + if (%obj.velocityMod !$= "") %buildingPiece = %buildingPiece @ "velocityMod = \"" @ %obj.velocityMod @ "\";"; + if (%obj.gravityMod !$= "") %buildingPiece = %buildingPiece @ "gravityMod = \"" @ %obj.gravityMod @ "\";"; + if (%obj.appliedForce !$= "") %buildingPiece = %buildingPiece @ "appliedForce = \"" @ %obj.appliedForce @ "\";"; + if (%obj.powerFreq !$= "") %buildingPiece = %buildingPiece @ "powerFreq = \"" @ %obj.powerFreq @ "\";"; + if (%obj.isSwitchedOff !$= "") %buildingPiece = %buildingPiece @ "isSwitchedOff = \"" @ %obj.isSwitchedOff @ "\";"; + if (%obj.switchRadius !$= "") %buildingPiece = %buildingPiece @ "switchRadius = \"" @ %obj.switchRadius @ "\";"; + if (%obj.holoBlock !$= "") %buildingPiece = %buildingPiece @ "holoBlock = \"" @ %obj.holoBlock @ "\";"; + if (%obj.noSlow !$= "") %buildingPiece = %buildingPiece @ "noSlow = \"" @ %obj.noSlow @ "\";"; + if (%obj.static !$= "") %buildingPiece = %buildingPiece @ "static = \"" @ %obj.static @ "\";"; + if (%obj.timed !$= "") %buildingPiece = %buildingPiece @ "timed = \"" @ %obj.timed @ "\";"; + if (%obj.beamRange !$= "") %buildingPiece = %buildingPiece @ "beamRange = \"" @ %obj.beamRange @ "\";"; + if (%obj.tripMode !$= "") %buildingPiece = %buildingPiece @ "tripMode = \"" @ %obj.tripMode @ "\";"; + if (%obj.fieldMode !$= "") %buildingPiece = %buildingPiece @ "fieldMode = \"" @ %obj.fieldMode @ "\";"; + if (%dataBlockName $= "TelePadDeployedBase") { + if (%obj.frequency !$= "") %buildingPiece = %buildingPiece @ "frequency = \"" @ %obj.frequency @ "\";"; + if (%obj.teleMode !$= "") %buildingPiece = %buildingPiece @ "teleMode = \"" @ %obj.teleMode @ "\";"; + } + if (%obj.getType() & $TypeMasks::TurretObjectType) { + if (%obj.isSeeker !$= "") %buildingPiece = %buildingPiece @ "isSeeker = \"" @ %obj.isSeeker @ "\";"; + %barrel = %obj.getMountedImage(0); + if (%barrel > 0) + %buildingPiece = %buildingPiece @ "initialBarrel = \"" @ %barrel.getName() @ "\";"; + } + %buildingPiece = %buildingPiece @ "};"; + if (%obj.getTarget() != -1) %buildingPiece = %buildingPiece @ "setTargetSensorGroup(%building.getTarget()," @ mAbs(%obj.team) @ ");"; + %buildingPiece = %buildingPiece @ "addToDeployGroup(%building);"; + if (%obj.noSlow !$= "") %buildingPiece = %buildingPiece @ "%building.pzone.delete();%building.pzone = \"\";"; + if (%dataBlockName $= "DeployedEnergizer" || %dataBlockName $= "DeployedStationInventory" || %dataBlockName $= "StationInventory" + || %dataBlockName $= "TurretDeployedFloorIndoor" || %dataBlockName $= "TurretDeployedWallIndoor" || %dataBlockName $= "TurretDeployedCeilingIndoor" + || %dataBlockName $= "TurretDeployedOutdoor" || %dataBlockName $= "DeployedPulseSensor" + || %dataBlockName $= "LaserDeployed" || %dataBlockName $= "MissileRackTurretDeployed" || %dataBlockName $= "DiscTurretDeployed") { + %buildingPiece = %buildingPiece @ "%building.deploy();"; + if (%dataBlockName $= "StationInventory") + %buildingPiece = %buildingPiece @ "adjustTrigger(%building);"; + } + if (%obj.getDatablock().rechargeRate > 0 && !%obj.getDatablock().needsPower) %buildingPiece = %buildingPiece @ "%building.setSelfPowered();"; + if (%obj.getType() & $TypeMasks::TurretObjectType) + %buildingPiece = %buildingPiece @ "%building.setRechargeRate(%building.getDatablock().rechargeRate);"; + if (%obj.getDataBlock().className $= "Generator" || %obj.getDataBlock().className $= "Switch") { + if (%obj.isSwitchedOff) + %buildingPiece = %buildingPiece @ "setTargetName(%building.target,addTaggedString(\"Disabled Frequency\" SPC %building.powerFreq));"; + else + %buildingPiece = %buildingPiece @ "setTargetName(%building.target,addTaggedString(\"Frequency\" SPC %building.powerFreq));"; + if (%dataBlockName $= "DeployedSwitch") + %buildingPiece = %buildingPiece @ "setTargetSkin(%building.target,'" @ getTaggedString(getTargetSkin(%obj.target)) @ "');"; + if (!%obj.isSwitchedOff) + %buildingPiece = %buildingPiece @ "%building.playThread($AmbientThread,\"ambient\");"; + else { + if (%obj.isSwitchedOff) + // nb: doubles no. of power switches done, when loading switched off gens + %buildingPiece = %buildingPiece @ "%building.lastState = \"\";%building.getDataBlock().losePower(%building);"; + } + } + $SaveBuilding::Saved++; +// Ugly, but it works. May be cleaned up later. + if (isObject(%obj.lTarget)) { // We assume none of the later saved sub-objects need decon targets, could make this a subroutine + %target = %obj.lTarget; + %targetDataBlock = %target.getDatablock().getName(); + if (!$SaveBuilding::Quiet) + echo("Saving: " @ %target @ " Name: " @ %targetDataBlock); + %buildingPiece = %buildingPiece @ "%target = new StaticShape() {"; + %buildingPiece = %buildingPiece @ "datablock = \"" @ %targetDataBlock @ "\";"; + if (%target.position !$= "") %buildingPiece = %buildingPiece @ "position = \"" @ %target.position @ "\";"; + if (%target.rotation !$= "") %buildingPiece = %buildingPiece @ "rotation = \"" @ %target.rotation @ "\";"; + if (%target.scale !$= "") %buildingPiece = %buildingPiece @ "scale = \"" @ %target.scale @ "\";"; + if (%target.team) %buildingPiece = %buildingPiece @ "team = \"" @ %target.team @ "\";"; + %buildingPiece = %buildingPiece @ "lMain = %building;"; + %buildingPiece = %buildingPiece @ "};"; + %buildingPiece = %buildingPiece @ "%building.lTarget = %target;"; + %buildingPiece = %buildingPiece @ "addToDeployGroup(%target);"; + if (%target.getDatablock().rechargeRate > 0 && !%target.getDatablock().needsPower) %buildingPiece = %buildingPiece @ "%building.setSelfPowered();"; + } + if (%dataBlockName $= "DeployedMSpine") { + %left = %obj.left; + %right = %obj.right; + if (isObject(%left)) { + %leftDataBlock = %left.getDatablock().getName(); + if (!$SaveBuilding::Quiet) + echo("Saving: " @ %left @ " Name: " @ %leftDataBlock); + %buildingPiece = %buildingPiece @ "%left = new StaticShape() {"; + %buildingPiece = %buildingPiece @ "datablock = \"" @ %leftDataBlock @ "\";"; + if (%left.position !$= "") %buildingPiece = %buildingPiece @ "position = \"" @ %left.position @ "\";"; + if (%left.rotation !$= "") %buildingPiece = %buildingPiece @ "rotation = \"" @ %left.rotation @ "\";"; + if (%left.scale !$= "") %buildingPiece = %buildingPiece @ "scale = \"" @ %left.scale @ "\";"; + if (%left.team) %buildingPiece = %buildingPiece @ "team = \"" @ %left.team @ "\";"; + if (%left.needsFit) %buildingPiece = %buildingPiece @ "needsfit = \"" @ %left.needsFit @ "\";"; + %buildingPiece = %buildingPiece @ "};"; + %buildingPiece = %buildingPiece @ "%building.left = %left;"; + %buildingPiece = %buildingPiece @ "addToDeployGroup(%left);"; + if (%left.getDatablock().rechargeRate > 0 && !%left.getDatablock().needsPower) %buildingPiece = %buildingPiece @ "%building.setSelfPowered();"; + $SaveBuilding::Saved++; + } + if (isObject(%right)) { + %rightDataBlock = %right.getDatablock().getName(); + if (!$SaveBuilding::Quiet) + echo("Saving: " @ %right @ " Name: " @ %rightDataBlock); + %buildingPiece = %buildingPiece @ "%right = new StaticShape() {"; + %buildingPiece = %buildingPiece @ "datablock = \"" @ %rightDataBlock @ "\";"; + if (%right.position !$= "") %buildingPiece = %buildingPiece @ "position = \"" @ %right.position @ "\";"; + if (%right.rotation !$= "") %buildingPiece = %buildingPiece @ "rotation = \"" @ %right.rotation @ "\";"; + if (%right.scale !$= "") %buildingPiece = %buildingPiece @ "scale = \"" @ %right.scale @ "\";"; + if (%right.team) %buildingPiece = %buildingPiece @ "team = \"" @ %right.team @ "\";"; + if (%right.needsFit) %buildingPiece = %buildingPiece @ "needsfit = \"" @ %right.needsFit @ "\";"; + %buildingPiece = %buildingPiece @ "};"; + %buildingPiece = %buildingPiece @ "%building.right = %right;"; + %buildingPiece = %buildingPiece @ "addToDeployGroup(%right);"; + if (%right.getDatablock().rechargeRate > 0 && !%right.getDatablock().needsPower) %buildingPiece = %buildingPiece @ "%building.setSelfPowered();"; + $SaveBuilding::Saved++; + } + } + else if (%dataBlockName $= "TelePadDeployedBase") { + %beam = %obj.beam; + if (isObject(%beam)) { + %beamDataBlock = %beam.getDatablock().getName(); + if (!$SaveBuilding::Quiet) + echo("Saving: " @ %beam @ " Name: " @ %beamDataBlock); + %buildingPiece = %buildingPiece @ "%beam = new StaticShape() {"; + %buildingPiece = %buildingPiece @ "datablock = \"" @ %beamDataBlock @ "\";"; + if (%beam.position !$= "") %buildingPiece = %buildingPiece @ "position = \"" @ %beam.position @ "\";"; + if (%beam.rotation !$= "") %buildingPiece = %buildingPiece @ "rotation = \"" @ %beam.rotation @ "\";"; + if (%beam.scale !$= "") %buildingPiece = %buildingPiece @ "scale = \"" @ %beam.scale @ "\";"; + %buildingPiece = %buildingPiece @ "};"; + %buildingPiece = %buildingPiece @ "%building.beam = %beam;"; + %buildingPiece = %buildingPiece @ "%beam.playThread(0,\"ambient\");"; + %buildingPiece = %buildingPiece @ "%beam.setThreadDir(0,true);"; + %buildingPiece = %buildingPiece @ "%beam.flashThreadDir = true;"; + %buildingPiece = %buildingPiece @ "setTargetName(%building.target,addTaggedString(\"Frequency\" SPC %building.frequency));"; + } + } + else if (%dataBlockName $= "DeployedLogoProjector") { + %holo = %obj.holo; + if (isObject(%holo)) { + %holoDataBlock = %holo.getDatablock().getName(); + if (!$SaveBuilding::Quiet) + echo("Saving: " @ %holo @ " Name: " @ %holoDataBlock); + %buildingPiece = %buildingPiece @ "%holo = new StaticShape() {"; + %buildingPiece = %buildingPiece @ "datablock = \"" @ %holoDataBlock @ "\";"; + if (%holo.position !$= "") %buildingPiece = %buildingPiece @ "position = \"" @ %holo.position @ "\";"; + if (%holo.rotation !$= "") %buildingPiece = %buildingPiece @ "rotation = \"" @ %holo.rotation @ "\";"; + if (%holo.scale !$= "") %buildingPiece = %buildingPiece @ "scale = \"" @ %holo.scale @ "\";"; + %buildingPiece = %buildingPiece @ "};"; + %buildingPiece = %buildingPiece @ "%building.holo = %holo;"; + %buildingPiece = %buildingPiece @ "%holo.projector = %building;"; + } + } + else if (%dataBlockName $= "DeployedLightBase") { + %light = %obj.light; + if (isObject(%light)) { + %lightDataBlock = %light.getDatablock().getName(); + if (!$SaveBuilding::Quiet) + echo("Saving: " @ %light @ " Name: " @ %lightDataBlock); + %buildingPiece = %buildingPiece @ "%light = new Item() {"; + %buildingPiece = %buildingPiece @ "datablock = \"" @ %lightDataBlock @ "\";"; + %buildingPiece = %buildingPiece @ "static = true;"; + %buildingPiece = %buildingPiece @ "};"; + %buildingPiece = %buildingPiece @ "%building.light = %light;"; + %buildingPiece = %buildingPiece @ "%light.lightBase = %building;"; + %buildingPiece = %buildingPiece @ "adjustLight(%building);"; + } + } + else if (%dataBlockName $= "DeployedTripwire") { + %tripField = %obj.tripField; + if (isObject(%tripField)) { + %tripFieldDataBlock = %tripField.getDatablock().getName(); + if (!$SaveBuilding::Quiet) + echo("Saving: " @ %tripField @ " Name: " @ %tripFieldDataBlock); + %buildingPiece = %buildingPiece @ "%tripField = new ForceFieldBare() {"; + %buildingPiece = %buildingPiece @ "datablock = \"" @ %tripFieldDataBlock @ "\";"; + if (%tripField.scale !$= "") %buildingPiece = %buildingPiece @ "scale = \"" @ %tripField.scale @ "\";"; + %buildingPiece = %buildingPiece @ "};"; + %buildingPiece = %buildingPiece @ "%building.tripField = %tripField;"; + %buildingPiece = %buildingPiece @ "%tripField.pzone.delete();%building.pzone = \"\";"; + } + %tripTrigger = %obj.tripTrigger; + if (isObject(%tripTrigger)) { + %tripTriggerDataBlock = %tripTrigger.getDatablock().getName(); + if (!$SaveBuilding::Quiet) + echo("Saving: " @ %tripTrigger @ " Name: " @ %tripTriggerDataBlock); + %buildingPiece = %buildingPiece @ "%tripTrigger = new Trigger() {"; + %buildingPiece = %buildingPiece @ "datablock = \"" @ %tripTriggerDataBlock @ "\";"; + if (%tripTrigger.scale !$= "") %buildingPiece = %buildingPiece @ "scale = \"" @ %tripTrigger.scale @ "\";"; + if (%tripTrigger.polyhedron !$= "") %buildingPiece = %buildingPiece @ "polyhedron = \"" @ %tripTrigger.polyhedron @ "\";"; + %buildingPiece = %buildingPiece @ "};"; + %buildingPiece = %buildingPiece @ "%building.tripTrigger = %tripTrigger;"; + %buildingPiece = %buildingPiece @ "%tripTrigger.baseObj = %building;"; + } + %buildingPiece = %buildingPiece @ "setTargetName(%building.target,addTaggedString(\"Frequency\" SPC %building.powerFreq));"; + %buildingPiece = %buildingPiece @ "%building.deploy();"; + %buildingPiece = %buildingPiece @ "adjustTripwire(%building);"; + } + else if (%dataBlockName $= "DeployedEscapePod") { + %buildingPiece = %buildingPiece @ "adjustEscapePod(%building);"; + %buildingPiece = %buildingPiece @ "escapePodLoop(%building);"; + } + } + else { + if (!$SaveBuilding::Quiet) { +// warn("Skipping: " @ %obj @ " Name: " @ %dataBlockName); + } + %buildingPiece = ""; + $SaveBuilding::Skipped++; + } + + return %buildingPiece; +} + +// This function saves a building and relocates it to the center of the 'map' +// Optional switch to put center at lowest part of building +// +// NB: Position of objects (such as support beams) is their attachment point, +// not their actual center. This may give some 'strange' results when centering +// small buildings + +function saveBuildingCentered(%cl,%rad,%file,%quiet,%centerAtMinZ) { + if (%quiet == true) { + $SaveBuilding::Quiet = true; + } + else { + $SaveBuilding::Quiet = false; // Overwrite + } + if (!isObject(%cl)) { + if (isObject(nameToID(LocalClientConnection))) { + %cl = nameToID(LocalClientConnection); + } + else { + if ($CurrentClientId) { + %cl = $CurrentClientId; + } + } + } + if (%rad < 1) { + %rad = 100000; + } + %buildingCount = 0; + if (%file $= "") { + for(%found = true; %found; %buildingCount++ ) { + %suffix = %buildingCount; + while (strLen(%suffix) < 5) %suffix = "0" @ %suffix; + %file = $SaveBuilding::SaveFolder @ %cl.nameBase @ "-" @ $MissionName @ "-" @ %suffix @ ".cs"; + %found = isFile(%file); + } + } + else { + %file = $SaveBuilding::SaveFolder @ %file; + } + + if (isObject(%cl.getControlObject())) { + %pos = %cl.getControlObject().getPosition(); + } + if (!%pos) { + %pos = "0 0 0"; + } + new fileObject("Building"); + if (!$SaveBuilding::Quiet) { + warn("Saving to file: \"" @ %file @ "\""); + } + Building.openForWrite(%file); + Building.writeLine("// CONSTRUCTION MOD SAVE FILE"); + Building.writeLine("// This building was saved by \"" @ getField(%cl.nameBase,0) @ "\""); + Building.writeLine("// This building was created in mission \"" @ $MissionName @ "\""); + Building.writeLine(""); + + $SaveBuilding::Saved = 0; + $SaveBuilding::Skipped = 0; + $SaveBuilding::MaxX = 0; + $SaveBuilding::MaxY = 0; + $SaveBuilding::MaxZ = 0; + $SaveBuilding::MinX = 0; + $SaveBuilding::MinY = 0; + $SaveBuilding::MinZ = 0; + + %firstObj = true; + initContainerRadiusSearch(%pos,%rad,$TypeMasks::StaticShapeObjectType | $TypeMasks::ForceFieldObjectType | $TypeMasks::ItemObjectType); + while((%obj = containerSearchNext()) != 0) { + %compPos = checkBuildingComponentCentered(%obj); + if (%compPos) { + %x = getWord(%compPos,0); + %y = getWord(%compPos,1); + %z = getWord(%compPos,2); + if (%x > $SaveBuilding::MaxX || %firstObj) {$SaveBuilding::MaxX = %x;} + if (%y > $SaveBuilding::MaxY || %firstObj) {$SaveBuilding::MaxY = %y;} + if (%z > $SaveBuilding::MaxZ || %firstObj) {$SaveBuilding::MaxZ = %z;} + if (%x < $SaveBuilding::MinX || %firstObj) {$SaveBuilding::MinX = %x;} + if (%y < $SaveBuilding::MinY || %firstObj) {$SaveBuilding::MinY = %y;} + if (%z < $SaveBuilding::MinZ || %firstObj) {$SaveBuilding::MinZ = %z;} + %firstObj = false; + } + } + + $SaveBuilding::SizeX = $SaveBuilding::MaxX - $SaveBuilding::MinX; + $SaveBuilding::SizeY = $SaveBuilding::MaxY - $SaveBuilding::MinY; + $SaveBuilding::SizeZ = $SaveBuilding::MaxZ - $SaveBuilding::MinZ; + + $SaveBuilding::CenterX = $SaveBuilding::MinX + ($SaveBuilding::SizeX / 2); + $SaveBuilding::CenterY = $SaveBuilding::MinY + ($SaveBuilding::SizeY / 2); + if (!%centerAtMinZ) {$SaveBuilding::CenterZ = $SaveBuilding::MinZ + ($SaveBuilding::SizeZ / 2);} + else {$SaveBuilding::CenterZ = $SaveBuilding::MinZ;} + + if (isObject($SaveBuilding::TestWaypoint)) + $SaveBuilding::TestWaypoint.delete(); + $SaveBuilding::TestWaypoint = new WayPoint(SaveBuildingWaypoint) { + position = $SaveBuilding::CenterX SPC $SaveBuilding::CenterY SPC $SaveBuilding::CenterZ; + rotation = "1 0 0 0"; + scale = "1 1 1"; + dataBlock = "WayPointMarker"; + team = 0; + name = "Saved Building Center"; + }; + MissionCleanup.add($SaveBuilding::TestWaypoint); + + initContainerRadiusSearch(%pos,%rad,$TypeMasks::StaticShapeObjectType | $TypeMasks::ForceFieldObjectType | $TypeMasks::ItemObjectType); + while((%obj = containerSearchNext()) != 0) { + %cmp = writeBuildingComponentCentered(%obj); + if (%cmp !$= "") { + Building.writeLine(%cmp); + } + } + + if (!$SaveBuilding::Quiet) { + warn("Saved to file: \"" @ %file @ "\""); + warn("Saved pieces: " @ $SaveBuilding::Saved); + warn("Skipped pieces: " @ $SaveBuilding::Skipped); + } + + $SaveBuilding::LastFile = %file; + + Building.close(); + Building.delete(); + return %file; +} + +function checkBuildingComponentCentered(%obj) { + %save = false; + %save = saveBuildingCheck(%obj); + if (%save == true) { + %pos = %obj.position; + %x = getWord(%pos,0); + %y = getWord(%pos,1); + %z = getWord(%pos,2); + %obj.saveBuilding = true; + return %x SPC %y SPC %z; + } + else { + %obj.saveBuilding = false; + return; + } +} + +function writeBuildingComponentCentered(%obj) { + %dataBlockName = %obj.getDatablock().getName(); + %save = false; + %save = saveBuildingCheck(%obj); + if (%save == true) { + if (!$SaveBuilding::Quiet) + echo("Saving: " @ %obj @ " Name: " @ %dataBlockName); + %buildingPiece = "%building = new (" @ %obj.getClassName() @ ") () {"; + %buildingPiece = %buildingPiece @ "datablock = \"" @ %dataBlockName @ "\";"; + %pos = %obj.position; + %x = getWord(%pos,0)-$SaveBuilding::CenterX; + %y = getWord(%pos,1)-$SaveBuilding::CenterY; + %z = getWord(%pos,2)-$SaveBuilding::CenterZ; + %savePos = %x SPC %y SPC %z; + if (%obj.position !$= "") %buildingPiece = %buildingPiece @ "position = \"" @ %savePos @ "\";"; + if (%obj.rotation !$= "") %buildingPiece = %buildingPiece @ "rotation = \"" @ %obj.rotation @ "\";"; + if (%obj.realScale !$= "") %buildingPiece = %buildingPiece @ "scale = \"" @ %obj.realScale @ "\";"; + else {if (%obj.scale !$= "") %buildingPiece = %buildingPiece @ "scale = \"" @ %obj.scale @ "\";";} + if (%obj.impulse !$= "") %buildingPiece = %buildingPiece @ "impulse = \"" @ %obj.impulse @ "\";"; + if (%obj.frequency !$= "") %buildingPiece = %buildingPiece @ "frequency = \"" @ %obj.frequency @ "\";"; + %buildingPiece = %buildingPiece @ "};"; + $SaveBuilding::Saved++; + } + else { + if (!$SaveBuilding::Quiet) { +// warn("Skipping: " @ %obj @ " Name: " @ %dataBlockName); + } + %buildingPiece = ""; + $SaveBuilding::Skipped++; + } + + return %buildingPiece; +} + +function delBuildingWaypoint() { + if (isObject($SaveBuilding::TestWaypoint)) + $SaveBuilding::TestWaypoint.delete(); +} + +function loadBuilding(%file) { + compile($SaveBuilding::SaveFolder @ %file); // Just in case it bombs out + exec($SaveBuilding::SaveFolder @ %file); +} + +function saveBuildingTimer(%timeInSeconds,%globalEcho,%file,%useMultipleFiles,%isScheduled,%threadCount) { + if (!%isScheduled) { + $SaveBuilding::TimerCount++; + $SaveBuilding::TimerTime = %timeInSeconds * 1000; + if ($SaveBuilding::TimerTime < 1) + $SaveBuilding::TimerTime = $SaveBuilding::TimerDefaultTime; + $SaveBuilding::TimerFile = %file; + if ($SaveBuilding::TimerFile $= "" || $SaveBuilding::TimerFile $= "0") + $SaveBuilding::TimerFile = "SaveBuildingTimer.cs"; + if (%useMultipleFiles) + $SaveBuilding::TimerFile = ""; + $SaveBuilding::TimerGlobalChatEcho = %globalEcho; + $SaveBuilding::TimerEnabled = true; + %threadCount = $SaveBuilding::TimerCount; + } + if ($SaveBuilding::TimerEnabled == true && $SaveBuilding::TimerCount == %threadCount && isObject("MissionCleanup/Deployables")) { + %file = saveBuilding(0,0,$SaveBuilding::TimerFile,true,true); + %timeToNextSave = mFloatLength($SaveBuilding::TimerTime / 60 / 1000,2); + %timeToNextSaveMinutes = mFloor(%timeToNextSave); + %timeToNextSaveSeconds = mFloor((%timeToNextSave - %timeToNextSaveMinutes) * 60); + %timeToNextSave = %timeToNextSaveMinutes @ "m, " @ %timeToNextSaveSeconds @ "s"; + %filespec = "\"" @ %file @ "\""; + if ($SaveBuilding::TimerFile $= "") + %filespec = %filespec @ " (using multiple files)"; + warn("-SaveBuildingTimer- Saved to: " @ %filespec @ " - Timer: " @ %timeToNextSave); + if ($SaveBuilding::TimerGlobalChatEcho) + MessageAll('msgClient',"\c2Buildings saved. Next save in " @ %timeToNextSave); + if ($SaveBuilding::TimerTime > 0) // Extra safety + schedule($SaveBuilding::TimerTime,0,saveBuildingTimer,0,0,0,0,true,%threadCount); + } + else { + warn("-SaveBuildingTimer- Thread " @ %threadCount @ " disabled. Last active thread: " @ $SaveBuilding::TimerCount); + } +} + +// NB: This function does not setup default parameters +function saveBuildingTimerOn() { + if ($SaveBuilding::TimerTime < 1) { + $SaveBuilding::TimerTime = $SaveBuilding::TimerDefaultTime; + } + $SaveBuilding::TimerCount++; + $SaveBuilding::TimerEnabled = true; + saveBuildingTimer(0,0,0,0,true,$SaveBuilding::TimerCount); +} + +function saveBuildingTimerOff() { + $SaveBuilding::TimerEnabled = false; +} + +function delDupPieces(%cl,%rad,%quiet) { + %randomTime = 10000; + if (%quiet == true) { + $SaveBuilding::Quiet = true; + } + else { + $SaveBuilding::Quiet = false; // Overwrite + } + if (!isObject(%cl)) { + if (isObject(nameToID(LocalClientConnection))) { + %cl = nameToID(LocalClientConnection); + } + else { + if ($CurrentClientId) { + %cl = $CurrentClientId; + } + } + } + if (%rad < 1) { + %rad = 100000; + } + if (isObject(%cl.getControlObject())) { + %pos = %cl.getControlObject().getPosition(); + } + if (!%pos) { + %pos = "0 0 0"; + } + %oldChk = ""; + initContainerRadiusSearch(%pos,%rad,$TypeMasks::StaticShapeObjectType | $TypeMasks::ForceFieldObjectType | $TypeMasks::ItemObjectType); + while((%obj = containerSearchNext()) != 0) { + %dataBlockName = %obj.getDatablock().getName(); + %save = saveBuildingCheck(%obj); + if (%save) { + // Round down a bit + %objPos = mFloatLength(getWord(%obj.getPosition(),0),2) SPC mFloatLength(getWord(%obj.getPosition(),1),2) SPC mFloatLength(getWord(%obj.getPosition(),2),2); + %objRot = mFloatLength(getWord(%obj.rotation,0),2) SPC mFloatLength(getWord(%obj.rotation,1),2) SPC mFloatLength(getWord(%obj.rotation,2),2) SPC mFloatLength(getWord(%obj.rotation,3),2); + if (%obj.realScale) + %objScale = %obj.realScale; + else + %objScale = %obj.scale; + if (%dataBlockName $= "DeployedFloor" || %dataBlockName $= "DeployedwWall") + // This doesn't handle all wWalls, but it helps + %chk = %dataBlockName SPC %objPos SPC %objScale; + else + %chk = %dataBlockName SPC %objPos SPC %objRot SPC %objScale; + if (%chk $= %oldChk) { + %deleted++; + if (!$SaveBuilding::Quiet && %dataBlockName !$= "DeployedMSpineRing") + warn("Deleting: " @ %oldObj @ " Name: " @ %dataBlockName); + // from inventoryHud.cs, modified + %random = getRandom() * %randomTime; + // Not the best way of doing this.. + if ($SaveBuilding::QuickDelete == true) { + // Handle special cases + if (%dataBlockName $= "DeployedMSpine") { + if (isObject(%oldObj.left)) { + if (!$SaveBuilding::Quiet) + warn("Deleting: " @ %oldObj.left @ " Name: " @ %oldObj.left.getDatablock().getName()); + %deleted++; + remDSurface(%oldObj.left); + %oldObj.left.delete(); + } + if (isObject(%oldObj.right)) { + if (!$SaveBuilding::Quiet) + warn("Deleting: " @ %oldObj.right @ " Name: " @ %oldObj.right.getDatablock().getName()); + %deleted++; + remDSurface(%oldObj.right); + %oldObj.right.delete(); + } + remDSurface(%oldObj); + %oldObj.delete(); + } + else if (%dataBlockName $= "DeployedEscapePod") { + if (isObject(%oldObj.lTarget)) { + if (!$SaveBuilding::Quiet) + warn("Deleting: " @ %oldObj.lTarget @ " Name: " @ %oldObj.lTarget.getDatablock().getName()); + %deleted++; + remDSurface(%oldObj.lTarget); + %oldObj.lTarget.delete(); + } + if (isObject(%oldObj.podVehicle)) { + if (!$SaveBuilding::Quiet) + warn("Deleting: " @ %oldObj.podVehicle @ " Name: " @ %oldObj.podVehicle.getDatablock().getName()); + %deleted++; + %oldObj.podVehicle.delete(); + } + %oldObj.delete(); + } + else if (%dataBlockName $= "DeployedMSpineRing") { + // Nil. Handled by DeployedMSpine + %deleted--; + } + else if (%dataBlockName $= "TelePadBeam") { + // Nil. Handled by TelePadDeployedBase + %deleted--; + } + else if (%dataBlockName $= "DeployedLTarget") { + // Nil. Handled by parent object + %deleted--; + } + else { + if (%oldObj.beam) + %oldObj.beam.delete(); + if (%oldObj.pzone) + %oldObj.pzone.delete(); + if (%oldObj.trigger) + %oldObj.trigger.delete(); + if (%oldObj.lTarget) + %oldObj.lTarget.delete(); + if (%oldObj.holo) + %oldObj.holo.delete(); + if (%oldObj.light) + %oldObj.light.delete(); + if (%oldObj.tripField) + %oldObj.tripField.delete(); + if (%oldObj.tripTrigger) + %oldObj.tripTrigger.delete(); + remDSurface(%oldObj); + %oldObj.delete(); + } + } + else { + // Handle special cases + if (%dataBlockName $= "DeployedMSpineRing") { + // Nil. Handled by DeployedMSpine + } + else if (%dataBlockName $= "TelePadBeam") { + // Nil. Handled by TelePadDeployedBase + } + else if (%dataBlockName $= "DeployedLTarget") { + // Nil. Handled by parent object + } + else { + %oldObj.getDataBlock().schedule(%random,"disassemble",0, %oldObj); // Run Item Specific code. + } + } + } + else { + %checked++; +// if (!$SaveBuilding::Quiet) +// echo("Checking: " @ %obj @ " Name: " @ %dataBlockName); + } + %oldChk = %chk; + %oldObj = %obj; + } + else { + %skipped++; +// if (!$SaveBuilding::Quiet) +// warn("Skipping: " @ %obj @ " Name: " @ %dataBlockName); + } + } + + if (!$SaveBuilding::Quiet) { + warn("Checked pieces: " @ %checked); + warn("Skipped pieces: " @ %skipped); + warn("Deleted pieces: " @ %deleted); + } + return %randomTime; +} + +function updateDeployedCount() { + Game.clearDeployableMaxes(); + %group = nameToID("MissionCleanup/Deployables"); + %count = %group.getCount(); + for(%i=0;%i<%count;%i++) { + %obj = %group.getObject(%i); + %revItem = $ReverseDeployItem[%obj.getDataBlock().getName()]; + if (getWord(%revItem,0) $= "poof") + %revItem = getWord(%revItem,1); + if (%revItem !$= "") + $TeamDeployedCount[%obj.team,%revItem]++; + } +} diff --git a/scripts/server.cs b/scripts/server.cs new file mode 100644 index 0000000..d3f9d5f --- /dev/null +++ b/scripts/server.cs @@ -0,0 +1,2797 @@ +// Set the version of the mod here +$ModVersion = "v0.70 Development Version 1"; +$ModCredits = ""; + +if ($Host::TimeLimit $= "") + $Host::TimeLimit = 20; + +$SB::WODec = 0.004; // whiteout +$SB::DFDec = 0.02; // damageFlash + +// z0dd - ZOD, 10/06/02. Set this as base default, +// modders can change this value to match theirs. +$DefaultGravity = -20; + +// ----------------------------------------------------- +// z0dd - ZOD, 5/27/02. Addition. Tribes2.exe will call +// this for competition mod to alert players on server +// during tournament that a remote connection has been +// established to the server. +function onTelnetConnect(%ip, %access) +{ + // Thou shall not spam +} + +// z0dd - ZOD, 9/13/02. Anti spam +function serverCMDpracticeHudInitialize(%client, %val) +{ + // Thou shall not spam +} + +function VerifyCDCheck(%func) +{ + if (!cdFileCheck()) + messageBoxOkCancel("TRIBES 2 CD CHECK", "You must have the Tribes 2 CD in the CD-ROM drive while playing Tribes 2. Please insert the CD.", "schedule(0, 0, VerifyCDCheck, " @ %func @ ");", "quit();"); + else + call(%func); +} + +function logEcho(%msg) +{ + if ($LogEchoEnabled) + echo("LOG: " @ %msg); +} + +function CreateServer(%mission, %missionType) +{ + DestroyServer(); + + // Load server data blocks + exec("scripts/commanderMapIcons.cs"); + exec("scripts/markers.cs"); + exec("scripts/serverAudio.cs"); + exec("scripts/damageTypes.cs"); + exec("scripts/deathMessages.cs"); + exec("scripts/inventory.cs"); + exec("scripts/camera.cs"); + exec("scripts/particleEmitter.cs"); // Must exist before item.cs and explosion.cs + exec("scripts/particleDummies.cs"); + exec("scripts/projectiles.cs"); // Must exits before item.cs + exec("scripts/player.cs"); + exec("scripts/gameBase.cs"); + exec("scripts/staticShape.cs"); + exec("scripts/nerf.cs"); + exec("scripts/weapons.cs"); + exec("scripts/turret.cs"); + exec("scripts/weapTurretCode.cs"); + //exec("scripts/truPhysics.cs"); + exec("scripts/functions.cs"); + exec("scripts/do_not_delete/loadscreen.cs"); + exec("scripts/libraries.cs"); + exec("scripts/do_not_delete/Dfunctions.cs"); + exec("scripts/hfunctions.cs"); + exec("scripts/pack.cs"); + exec("scripts/vehicles/vehicle_spec_fx.cs"); // Must exist before other vehicle files or CRASH BOOM + exec("scripts/vehicles/serverVehicleHud.cs"); + exec("scripts/vehicles/vehicle_shrike.cs"); + exec("scripts/vehicles/vehicle_bomber.cs"); + exec("scripts/vehicles/vehicle_havoc.cs"); + exec("scripts/vehicles/vehicle_wildcat.cs"); + exec("scripts/vehicles/vehicle_tank.cs"); + exec("scripts/vehicles/vehicle_mpb.cs"); + exec("scripts/vehicles/vehicle_superHavoc.cs"); + exec("scripts/vehicles/vehicle_superWildcat.cs"); + exec("scripts/vehicles/vehicle_artillery.cs"); + exec("scripts/vehicles/vehicle_escapepod.cs"); + exec("scripts/vehicles/vehicle.cs"); // Must be added after all other vehicle files or EVIL BAD THINGS + exec("scripts/ai.cs"); + exec("scripts/item.cs"); + exec("scripts/station.cs"); + exec("scripts/simGroup.cs"); + exec("scripts/trigger.cs"); + exec("scripts/forceField.cs"); + exec("scripts/lightning.cs"); + exec("scripts/weather.cs"); + exec("scripts/deployables.cs"); + exec("scripts/stationSetInv.cs"); + exec("scripts/navGraph.cs"); + exec("scripts/targetManager.cs"); + exec("scripts/serverCommanderMap.cs"); + exec("scripts/environmentals.cs"); + exec("scripts/power.cs"); + exec("scripts/serverTasks.cs"); + exec("scripts/admin.cs"); + exec("prefs/banlist.cs"); + exec("scripts/savebuilding.cs"); + exec("scripts/JTLmeteorStorm.cs"); + exec("scripts/prison.cs"); + exec("scripts/hazard.cs"); + exec("scripts/ion.cs"); + exec("scripts/solitudeBlock.cs"); + exec("scripts/chatCommands.cs"); + if (!$Host::MTC::NoLoad) + exec("scripts/MTC_core.cs"); + exec("scripts/skywrite.cs"); + exec("scripts/dEffects.cs"); + + //Wierd placing due to dependencies. + exec("scripts/mpm/mpm_blast.cs"); + exec("scripts/mpm/mpm_launch.cs"); + exec("scripts/mpm/mpm.cs"); + exec("scripts/mpm/mpm_base.cs"); + exec("scripts/packs/antinuketurret.cs"); + exec("scripts/mpm/nuke_cannon.cs"); + exec("scripts/mpm/Nuclear_blast.cs"); + exec("scripts/weapons/dragonmissile.cs"); + // TODO - fix TR2 game screwing up here + //automatically load any mission type that follows naming convention typeGame.name.cs + if (!isDemo()) + { + %search = "scripts/*Game.cs"; + for(%file = findFirstFile(%search); %file !$= ""; %file = findNextFile(%search)) + { + %type = fileBase(%file); // get the name of the script + exec("scripts/" @ %type @ ".cs"); + } + } + //the DEMO version only uses DefaultGame.cs and SinglePlayerGame.cs + else + { + exec("scripts/DefaultGame.cs"); + exec("scripts/SinglePlayerGame.cs"); + exec("scripts/CTFGame.cs"); + exec("scripts/HuntersGame.cs"); + } + + $missionSequence = 0; + $CurrentMissionType = %missionType; + $HostGameBotCount = 0; + $HostGamePlayerCount = 0; + if ( $HostGameType !$= "SinglePlayer" ) + allowConnections(true); + $ServerGroup = new SimGroup (ServerGroup); + if (%mission $= "") + { + %mission = $HostMissionFile[$HostMission[0,0]]; + %missionType = $HostTypeName[0]; + } + + if ( ( isDemo() && $HostGameType !$= "SinglePlayer" ) || ( $HostGameType $= "Online" && $pref::Net::DisplayOnMaster !$= "Never" ) ) + schedule(0,0,startHeartbeat); + + // setup the bots for this server + if ( !isDemo() && $Host::BotsEnabled ) + initGameBots( %mission, %missionType ); + + // load the mission... + loadMission(%mission, %missionType, true); +} + +function initGameBots( %mission, %mType ) +{ + echo( "adding bots..." ); + + AISystemEnabled( false ); + if ( $Host::BotCount > 0 && %mType !$= "SinglePlayer" ) + { + // Make sure this mission is bot enabled: + for ( %idx = 0; %idx < $HostMissionCount; %idx++ ) + { + if ( $HostMissionFile[%idx] $= %mission ) + break; + } + + if ( $BotEnabled[%idx] ) + { + if ( $Host::BotCount > 16 ) + $HostGameBotCount = 16; + else + $HostGameBotCount = $Host::BotCount; + + if ( $Host::BotCount > $Host::MaxPlayers - 1 ) + $HostGameBotCount = $Host::MaxPlayers - 1; + + //set the objective reassessment timeslice var + $AITimeSliceReassess = 0; + aiConnectMultiple( $HostGameBotCount, $Host::MinBotDifficulty, $Host::MaxBotDifficulty, -1 ); + } + else + { + $HostGameBotCount = 0; + } + } +} + +function findNextCycleMission() +{ + %numPlayers = ClientGroup.getCount(); + %tempMission = $CurrentMission; + %failsafe = 0; + while (1) + { + %nextMissionIndex = getNextMission(%tempMission, $CurrentMissionType); + %nextPotentialMission = $HostMissionFile[%nextMissionIndex]; + + //just cycle to the next if we've gone all the way around... + if (%nextPotentialMission $= $CurrentMission || %failsafe >= 1000) + { + %nextMissionIndex = getNextMission($CurrentMission, $CurrentMissionType); + // z0dd - ZOD - Founder, 10/06/02. Was trying to load a mission name instead of file. + //return $HostMissionName[%nextMissionIndex]; + return $HostMissionFile[%nextMissionIndex]; + } + + //get the player count limits for this mission + %limits = $Host::MapPlayerLimits[%nextPotentialMission, $CurrentMissionType]; + if (%limits $= "") + return %nextPotentialMission; + else + { + %minPlayers = getWord(%limits, 0); + %maxPlayers = getWord(%limits, 1); + + if ((%minPlayers < 0 || %numPlayers >= %minPlayers) && (%maxPlayers < 0 || %numPlayers <= %maxPlayers)) + return %nextPotentialMission; + } + + //since we didn't return the mission, we must not have an acceptable number of players - check the next + %tempMission = %nextPotentialMission; + %failsafe++; + } +} + +function CycleMissions() +{ + echo( "cycling mission. " @ ClientGroup.getCount() @ " clients in game." ); + %nextMission = findNextCycleMission(); + messageAll( 'MsgClient', 'Loading %1 (%2)...', %nextMission, $MissionTypeDisplayName ); + loadMission( %nextMission, $CurrentMissionType ); +} + +function DestroyServer() +{ + $missionRunning = false; + allowConnections(false); + stopHeartbeat(); + if ( isObject( MissionGroup ) ) + MissionGroup.delete(); + if ( isObject( MissionCleanup ) ) + MissionCleanup.delete(); + if (isObject(game)) + { + game.deactivatePackages(); + game.delete(); + } + if (isObject($ServerGroup)) + $ServerGroup.delete(); + + // delete all the connections: + while(ClientGroup.getCount()) + { + %client = ClientGroup.getObject(0); + if (%client.isAIControlled()) + %client.drop(); + else + %client.delete(); + } + + // delete all the data blocks... + // this will cause problems if there are any connections + deleteDataBlocks(); + + // reset the target manager + resetTargetManager(); + + echo( "exporting server prefs..." ); + export( "$Host::*", "prefs/ServerPrefs.cs", false ); + purgeResources(); + + // TR2 + // This is a failsafe way of ensuring that default gravity is always restored + // if a game type (such as TR2) changes it. It is placed here so that listen + // servers will work after opening and closing different gametypes. + if ($DefaultGravity !$= "") + setGravity($DefaultGravity); +} + +function Disconnect() +{ + if ( isObject( ServerConnection ) ) + ServerConnection.delete(); + DisconnectedCleanup(); + DestroyServer(); +} + +function DisconnectedCleanup() +{ + $CurrentMissionType = ""; + $CurrentMission = ""; + + // Make sure we're not still waiting for the loading info: + cancelLoadInfoCheck(); + + // clear the chat hud message vector + HudMessageVector.clear(); + if ( isObject( PlayerListGroup ) ) + PlayerListGroup.delete(); + + // terminate all playing sounds + alxStopAll(); + + // clean up voting + voteHud.voting = false; + mainVoteHud.setvisible(0); + + // clear all print messages + clientCmdclearBottomPrint(); + clientCmdClearCenterPrint(); + + // clear the inventory and weapons hud + weaponsHud.clearAll(); + inventoryHud.clearAll(); + + // back to the launch screen + Canvas.setContent(LaunchGui); + if ( isObject( MusicPlayer ) ) + MusicPlayer.stop(); + clearTextureHolds(); + purgeResources(); + + if ( $PlayingOnline ) + { + // Restart the email check: + if ( !EmailGui.checkingEmail && EmailGui.checkSchedule $= "" ) + CheckEmail( true ); + + IRCClient::onLeaveGame(); + } +} + +// we pass the guid as well, in case this guy leaves the server. +function kick( %client, %admin, %guid ) +{ + if(%admin) // z0dd - ZOD, 8/23/02. Let the player know who kicked him. + messageAll( 'MsgAdminForce', '\c2%2 has kicked %1.', Game.kickClientName, %admin.name ); + else + messageAll( 'MsgVotePassed', '\c2%1 was kicked by vote.', Game.kickClientName ); + + messageClient(%client, 'onClientKicked', ""); + messageAllExcept( %client, -1, 'MsgClientDrop', "", Game.kickClientName, %client ); + + if ( %client.isAIControlled() ) + { + //$HostGameBotCount--; // said it will fix the bug were when i kick a bot u get 255 bot count + %client.drop(); + } + else + { + if ( $playingOnline ) // won games + { + %count = ClientGroup.getCount(); + %found = false; + for( %i = 0; %i < %count; %i++ ) // see if this guy is still here... + { + %cl = ClientGroup.getObject( %i ); + if ( %cl.guid == %guid ) + { + %found = true; + + // kill and delete this client, their done in this server. + if ( isObject( %cl.player ) ) + %cl.player.scriptKill(0); + + if ( isObject( %cl ) ) + { + if(%admin) // z0dd - ZOD, 8/23/02. Let the player know who kicked him. + %cl.setDisconnectReason( %admin.nameBase @ "has kicked you out of the game." ); + else + %cl.setDisconnectReason( "You have been kicked out of the game." ); + + %cl.schedule(700, "delete"); + } + + BanList::add( %guid, "0", $Host::KickBanTime ); + } + } + if ( !%found ) + BanList::add( %guid, "0", $Host::KickBanTime ); // keep this guy out for a while since he left. + } + else // lan games + { + // kill and delete this client + if ( isObject( %client.player ) ) + %client.player.scriptKill(0); + + if ( isObject( %client ) ) + { + %client.setDisconnectReason( "You have been kicked out of the game." ); + %client.schedule(700, "delete"); + } + + BanList::add( 0, %client.getAddress(), $Host::KickBanTime ); + } + } +} + +function ban( %client, %admin ) +{ + if ( %admin ) // z0dd - ZOD, 8/23/02. Let the player know who kicked him. + messageAll('MsgAdminForce', '\c2%2 has banned %1.', %client.name, %admin.name); + else + messageAll( 'MsgVotePassed', '\c2%1 was banned by vote.', %client.name ); + + messageClient(%client, 'onClientBanned', ""); + messageAllExcept( %client, -1, 'MsgClientDrop', "", %client.name, %client ); + + // kill and delete this client + if ( isObject(%client.player) ) + %client.player.scriptKill(0); + + if ( isObject( %client ) ) + { + if(%admin) // z0dd - ZOD, 8/23/02. Let the player know who kicked him. + %client.setDisconnectReason( %admin.nameBase @ "has banned you from this server." ); + else + %client.setDisconnectReason( "You have been banned from this server." ); + + %client.schedule(700, "delete"); + } + + BanList::add(%client.guid, %client.getAddress(), $Host::BanTime); +} + +function getValidVoicePitch(%voice, %voicePitch) +{ + if (%voicePitch < -1.0) + %voicePitch = -1.0; + else if (%voicePitch > 1.0) + %voicePitch = 1.0; + + //Voice pitch range is from 0.5 to 2.0, however, we should tighten the range to + //avoid players sounding like mickey mouse, etc... + //see if we're pitching down - clamp the min pitch at 0.875 + if (%voicePitch < 0) + return (1.0 + (0.125 * %voicePitch)); + + //max voice pitch is 1.125 + else if (%voicePitch > 0) + return 1.0 + (0.125 * %voicePitch); + + else + return 1.0; +} + +$DemoNameCount = 0; +function addDemoAlias( %name ) +{ + $DemoName[$DemoNameCount] = %name; + $DemoNameCount++; +} + +if ( isDemo() ) +{ + addDemoAlias( "Butterfingers" ); + addDemoAlias( "Bullseye" ); + addDemoAlias( "Casualty" ); + addDemoAlias( "Dogfood" ); + addDemoAlias( "Extinct" ); + addDemoAlias( "Fodder" ); + addDemoAlias( "Grunt" ); + addDemoAlias( "Helpless" ); + addDemoAlias( "Itchy" ); + addDemoAlias( "Bait" ); + addDemoAlias( "Kibble" ); + addDemoAlias( "MonkeyBoy" ); + addDemoAlias( "Meat" ); + addDemoAlias( "Newbie" ); + addDemoAlias( "Owned" ); + addDemoAlias( "Poser" ); + addDemoAlias( "Quaker" ); + addDemoAlias( "Roadkill" ); + addDemoAlias( "SkidMark" ); + addDemoAlias( "EZTarget" ); + addDemoAlias( "Underdog" ); + addDemoAlias( "Vegetable" ); + addDemoAlias( "Weakling" ); + addDemoAlias( "Flatline" ); + addDemoAlias( "Spud" ); + addDemoAlias( "Zero" ); + addDemoAlias( "WetNose" ); + addDemoAlias( "Chowderhead" ); + addDemoAlias( "Clown" ); + addDemoAlias( "Dodo" ); + addDemoAlias( "Endangered" ); + addDemoAlias( "Feeble" ); + addDemoAlias( "Gimp" ); + addDemoAlias( "Inky" ); + addDemoAlias( "Pinky" ); + addDemoAlias( "Blinky" ); + addDemoAlias( "Clyde" ); + addDemoAlias( "Loopy" ); + addDemoAlias( "Masochist" ); + addDemoAlias( "Pancake" ); + addDemoAlias( "Rubbish" ); + addDemoAlias( "Sickly" ); + addDemoAlias( "Terminal" ); + addDemoAlias( "Ugly Duckling" ); + addDemoAlias( "Sheepish" ); + addDemoAlias( "Whiplash" ); + addDemoAlias( "KickMe" ); + addDemoAlias( "Yellow Belly" ); + addDemoAlias( "Bits" ); + addDemoAlias( "Doofus" ); + addDemoAlias( "Fluffy Bunny" ); + addDemoAlias( "Lollipop" ); + addDemoAlias( "Troglodyte" ); + addDemoAlias( "Carcass" ); + addDemoAlias( "Noodle" ); + addDemoAlias( "Spastic" ); + addDemoAlias( "Wimpy" ); + addDemoAlias( "Sweet Pea" ); + addDemoAlias( "Abused" ); + addDemoAlias( "Happy Camper" ); + addDemoAlias( "FreakShow" ); + addDemoAlias( "Bumpkin" ); + addDemoAlias( "Mad Cow" ); + addDemoAlias( "Cud" ); +} + +function pickDemoName() +{ + // Pick a unique name if possible: + %idx = mFloor( getRandom() * $DemoNameCount ); + for ( %i = 0; %i < $DemoNameCount; %i++ ) + { + %name = $DemoName[mMod( %idx + %i, $DemoNameCount )]; + %isUnique = true; + %count = ClientGroup.getCount(); + for ( %ci = 0; %ci < %count; %ci++ ) + { + if ( strcmp( %name, detag( getTaggedString( ClientGroup.getObject( %ci ).name ) ) ) == 0 ) + { + %isUnique = false; + break; + } + } + + if ( %isUnique ) + break; + } + + // Append a number to make the alias unique: + if ( !%isUnique ) + { + %suffix = 1; + while ( !%isUnique ) + { + %nameTry = %name @ "." @ %suffix; + %isUnique = true; + + %count = ClientGroup.getCount(); + for ( %i = 0; %i < %count; %i++ ) + { + if ( strcmp( %nameTry, detag( getTaggedString( ClientGroup.getObject( %i ).name ) ) ) == 0 ) + { + %isUnique = false; + break; + } + } + + %suffix++; + } + + // Success! + %name = %nameTry; + } + + return( %name ); +} + +function GameConnection::onConnect( %client, %name, %raceGender, %skin, %voice, %voicePitch ) +{ + %client.setMissionCRC($missionCRC); + sendLoadInfoToClient( %client ); + + //%client.setSimulatedNetParams(0.1, 30); + if (isDemo() && $CurrentMissionType !$= "SinglePlayer") + { + %client.armor = "Light"; + %client.sex = "Male"; + %client.race = "Human"; + %client.nameBase = pickDemoName(); + %client.name = addTaggedString( %client.nameBase ); + %client.voice = "Male1"; + %client.voiceTag = addTaggedString( "Male1" ); + if ( %client & 1 ) + %client.skin = addTaggedString( "swolf" ); + else + %client.skin = addTaggedString( "beagle" ); + } + else + { + // if hosting this server, set this client to superAdmin + if (%client.getAddress() $= "Local") + { + %client.isAdmin = true; + %client.isSuperAdmin = true; + } + + // Get the client's unique id: + %authInfo = %client.getAuthInfo(); + %client.guid = getField( %authInfo, 3 ); + + // check admin and super admin list, and set status accordingly + if ( !%client.isSuperAdmin ) + { + if ( isOnSuperAdminList( %client ) ) + { + %client.isAdmin = true; + %client.isSuperAdmin = true; + } + else if ( isOnAdminList( %client ) ) + { + %client.isAdmin = true; + } + } + + // Sex/Race defaults + switch$ ( %raceGender ) + { + case "Human Male": + %client.sex = "Male"; + %client.race = "Human"; + case "Human Female": + %client.sex = "Female"; + %client.race = "Human"; + case "Bioderm": + %client.sex = "Male"; + %client.race = "Bioderm"; + default: + error("Invalid race/gender combo passed: " @ %raceGender); + %client.sex = "Male"; + %client.race = "Human"; + } + %client.armor = "Light"; + + // Override the connect name if this server does not allow smurfs: + %realName = getField( %authInfo, 0 ); + if ( $PlayingOnline && $Host::NoSmurfs ) { + %client.smurfName = %name; + %name = %realName; + } + + if ( strcmp( %name, %realName ) == 0 ) + { + %client.isSmurf = false; + + //make sure the name is unique - that a smurf isn't using this name... + %dup = -1; + %count = ClientGroup.getCount(); + for (%i = 0; %i < %count; %i++) + { + %test = ClientGroup.getObject( %i ); + if (%test != %client) + { + %rawName = stripChars( detag( getTaggedString( %test.name ) ), "\cp\co\c6\c7\c8\c9" ); + if (%realName $= %rawName) + { + %dup = %test; + %dupName = %rawName; + break; + } + } + } + + //see if we found a duplicate name + if (isObject(%dup)) + { + //change the name of the dup + %isUnique = false; + %suffixCount = 1; + while (!%isUnique) + { + %found = false; + %testName = %dupName @ "." @ %suffixCount; + for (%i = 0; %i < %count; %i++) + { + %cl = ClientGroup.getObject(%i); + %rawName = stripChars( detag( getTaggedString( %cl.name ) ), "\cp\co\c6\c7\c8\c9" ); + if (%rawName $= %testName) + { + %found = true; + break; + } + } + + if (%found) + %suffixCount++; + else + %isUnique = true; + } + + //%testName will now have the new unique name... + %oldName = %dupName; + %newName = %testName; + + MessageAll( 'MsgSmurfDupName', '\c2The real \"%1\" has joined the server.', %dupName ); + MessageAll( 'MsgClientNameChanged', '\c2The smurf \"%1\" is now called \"%2\".', %oldName, %newName, %dup ); + + %dup.name = addTaggedString(%newName); + setTargetName(%dup.target, %dup.name); + } + + // Add the tribal tag: + %tag = getField( %authInfo, 1 ); + %append = getField( %authInfo, 2 ); + if ( %append ) + %name = "\cp\c6" @ %name @ "\c7" @ %tag @ "\co"; + else + %name = "\cp\c7" @ %tag @ "\c6" @ %name @ "\co"; + + %client.sendGuid = %client.guid; + } + else + { + %client.isSmurf = true; + %client.sendGuid = 0; + %name = stripTrailingSpaces( strToPlayerName( %name ) ); + if ( strlen( %name ) < 3 ) + %name = "Poser"; + + // Make sure the alias is unique: + %isUnique = true; + %count = ClientGroup.getCount(); + for ( %i = 0; %i < %count; %i++ ) + { + %test = ClientGroup.getObject( %i ); + %rawName = stripChars( detag( getTaggedString( %test.name ) ), "\cp\co\c6\c7\c8\c9" ); + if ( strcmp( %name, %rawName ) == 0 ) + { + %isUnique = false; + break; + } + } + + // Append a number to make the alias unique: + if ( !%isUnique ) + { + %suffix = 1; + while ( !%isUnique ) + { + %nameTry = %name @ "." @ %suffix; + %isUnique = true; + + %count = ClientGroup.getCount(); + for ( %i = 0; %i < %count; %i++ ) + { + %test = ClientGroup.getObject( %i ); + %rawName = stripChars( detag( getTaggedString( %test.name ) ), "\cp\co\c6\c7\c8\c9" ); + if ( strcmp( %nameTry, %rawName ) == 0 ) + { + %isUnique = false; + break; + } + } + + %suffix++; + } + + // Success! + %name = %nameTry; + } + + %smurfName = %name; + // Tag the name with the "smurf" color: + %name = "\cp\c8" @ %name @ "\co"; + } + + %client.name = addTaggedString(%name); + if (%client.isSmurf) + %client.nameBase = %smurfName; + else + %client.nameBase = %realName; + + // Make sure that the connecting client is not trying to use a bot skin: + %temp = detag( %skin ); + if ( %temp $= "basebot" || %temp $= "basebbot" ) + %client.skin = addTaggedString( "base" ); + else + %client.skin = addTaggedString( %skin ); + + if ($Host::NoAnnoyingVoiceChatSpam && %voice $= "") { + switch$ ( %raceGender ) { + case "Human Male": + %voice = "Male1"; + case "Human Female": + %voice = "Fem1"; + case "Bioderm": + %voice = "Derm1"; + default: + %voice = "Male1"; + } + } + + %client.voice = %voice; + %client.voiceTag = addtaggedString(%voice); + + //set the voice pitch based on a lookup table from their chosen voice + %client.voicePitch = getValidVoicePitch(%voice, %voicePitch); + } + + %client.justConnected = true; + %client.isReady = false; + + // full reset of client target manager + clientResetTargets(%client, false); + + %client.target = allocClientTarget(%client, %client.name, %client.skin, %client.voiceTag, '_ClientConnection', 0, 0, %client.voicePitch); + %client.score = 0; + %client.team = 0; + + $instantGroup = ServerGroup; + $instantGroup = MissionCleanup; + + echo("CADD: " @ %client @ " " @ %client.getAddress()); + + %count = ClientGroup.getCount(); + for(%cl = 0; %cl < %count; %cl++) + { + %recipient = ClientGroup.getObject(%cl); + if ((%recipient != %client)) + { + // These should be "silent" versions of these messages... + messageClient(%client, 'MsgClientJoin', "", + %recipient.name, + %recipient, + %recipient.target, + %recipient.isAIControlled(), + %recipient.isAdmin, + %recipient.isSuperAdmin, + %recipient.isSmurf, + %recipient.sendGuid); + + messageClient(%client, 'MsgClientJoinTeam', "", %recipient.name, $teamName[%recipient.team], %recipient, %recipient.team ); + } + } + +// commandToClient(%client, 'getManagerID', %client); + + commandToClient(%client, 'setBeaconNames', "Target Beacon", "Marker Beacon", "Bomb Target"); + + if ( $CurrentMissionType !$= "SinglePlayer" ) + { + if ( isDemo() ) + { + messageClient(%client, 'MsgClientJoin', '\c2Welcome to the Tribes 2 Demo!', + %client.name, + %client, + %client.target, + false, // isBot + %client.isAdmin, + %client.isSuperAdmin, + %client.isSmurf, + %client.sendGuid ); + } + else + { + messageClient(%client, 'MsgClientJoin', '\c2Welcome to Tribes2 %1.', + %client.name, + %client, + %client.target, + false, // isBot + %client.isAdmin, + %client.isSuperAdmin, + %client.isSmurf, + %client.sendGuid ); + } + + messageAllExcept(%client, -1, 'MsgClientJoin', '\c1%1 joined the game.', + %client.name, + %client, + %client.target, + false, // isBot + %client.isAdmin, + %client.isSuperAdmin, + %client.isSmurf, + %client.sendGuid ); + } + else + messageClient(%client, 'MsgClientJoin', "\c0Mission Insertion complete...", + %client.name, + %client, + %client.target, + false, // isBot + false, // isAdmin + false, // isSuperAdmin + false, // isSmurf + %client.sendGuid ); + + %opt = "\c2Server Options:"; + if ($MissionRunning == true) + %opt = %opt @ "\nTime limit: " @ mFloor((($Host::TimeLimit * 60 * 1000) + $missionStartTime - getSimTime())/1000/60) @ " / " @ $Host::TimeLimit; + else + %opt = %opt @ "\nTime limit: " @ $Host::TimeLimit; + %opt = %opt @ "\nMax players: " @ $Host::MaxPlayers @ + "\nTeam Damage: " @ ($Host::TeamDamageOn ? "On" : "Off") @ + "\nPurebuild: " @ ($Host::Purebuild ? "On" : "Off") @ + "\nCascade: " @ ($Host::Cascade ? "On" : "Off") @ + "\nHazard Mode: " @ ($Host::Hazard::Enabled ? "On" : "Off") @ + "\nMTC Mode: " @ ($Host::MTC::Enabled ? "On" : "Off") @ + "\nExpert Mode: " @ ($Host::ExpertMode ? "On" : "Off") @ + "\nPrison: " @ ($Host::Prison::Enabled ? "On" : "Off"); + + messageClient(%client,'msgClient',%opt); + + //Game.missionStart(%client); + setDefaultInventory(%client); + + if ($missionRunning) + %client.startMission(); + $HostGamePlayerCount++; + %client.demoJustJoined = true; + + + getRealName(%client); + + %logname = getTaggedString(%client.name); + %logname = strreplace(%logname,"\x10",""); + %logname = strreplace(%logname,"\x11",""); + %logname = strreplace(%logname,"\c8",""); + %logname = strreplace(%logname,"\c7",""); + %logname = strreplace(%logname,"\c6",""); + + %logExport = formatTimeString(yy) @ "/" @ formatTimeString(mm) @ "/" @ formatTimeString(dd); + %logExport = %logExport SPC formatTimeString(h) @ ":" @ formatTimeString(n) @ "." @ formatTimeString(s) SPC formatTimeString(a); + %logExport = %logExport SPC "Connection. " @ %client.getAddress() SPC " GUID: " @ %client.guid; + %logExport = %logExport SPC "Name: " @ %logname; + if (%client.isSmurf) + %logExport = %logExport SPC "Real Name: " @ getRealName(%client, "echo"); + + if ($Construction::Logging::LogConnects) + exportToLog(%logexport, "Logs/Connections/" @ formatTimeString(yy) @ "-" @ formatTimeString(mm) @ "-" @ formatTimeString(dd) @ ".log"); + +} + +function GameConnection::onDrop(%client, %reason) +{ + if (isObject(Game)) + Game.onClientLeaveGame(%client); + + // make sure that tagged string of player name is not used + if ( $CurrentMissionType $= "SinglePlayer" ) + messageAllExcept(%client, -1, 'MsgClientDrop', "", getTaggedString(%client.name), %client); + else + messageAllExcept(%client, -1, 'MsgClientDrop', '\c1%1 has left the game.', getTaggedString(%client.name), %client); + + %logname = getTaggedString(%client.name); + %logname = strreplace(%logname,"\x10",""); + %logname = strreplace(%logname,"\x11",""); + %logname = strreplace(%logname,"\c8",""); + %logname = strreplace(%logname,"\c7",""); + %logname = strreplace(%logname,"\c6",""); + + %logExport = formatTimeString(yy) @ "/" @ formatTimeString(mm) @ "/" @ formatTimeString(dd); + %logExport = %logExport SPC formatTimeString(h) @ ":" @ formatTimeString(n) @ "." @ formatTimeString(s) SPC formatTimeString(a); + %logExport = %logExport SPC "Disconnect. " @ %client.getAddress() SPC " GUID: " @ %client.guid; + %logExport = %logExport SPC "Name: " @ %logname; + if (%client.isSmurf) + %logExport = %logExport SPC "Real Name: " @ getRealName(%client, "echo"); + if ($Construction::Logging::LogConnects) + exportToLog(%logexport, "Logs/Connections/" @ formatTimeString(yy) @ "-" @ formatTimeString(mm) @ "-" @ formatTimeString(dd) @ ".log"); + + if ( isObject( %client.camera ) ) + %client.camera.delete(); + + removeTaggedString(%client.name); + removeTaggedString(%client.voiceTag); + removeTaggedString(%client.skin); + freeClientTarget(%client); + + echo("CDROP: " @ %client @ " " @ %client.getAddress()); + $HostGamePlayerCount--; + + // reset the server if everyone has left the game + if ( $HostGamePlayerCount - $HostGameBotCount == 0 && $Host::Dedicated && !$resettingServer && !$LoadingMission ) + schedule(0, 0, "resetServerDefaults"); +} + +function getRealName(%client, %sender) +{ + if(%client.isSmurf) + { + %authInfo = %client.getAuthInfo(); + %name = stripchars(detag(gettaggedstring(%client.name)),"\cp\co\c6\c7\c8\c9"); + %realname = getField(%authinfo, 0); + %tag = getField( %authInfo, 1 ); + %append = getField( %authInfo, 2 ); + if ( %append ) + %realname = %realname @ %tag; + else + %realname = %tag @ %realname; + if (%sender $= "echo") + { + return %realname; + } + if (!isObject(%sender)) + { + %count = ClientGroup.getCount(); + for(%i = 0; %i < %count; %i++) + { + %admin = ClientGroup.getObject(%i); + if(%admin.isAdmin) + messageClient(%admin, '', "\c2Smurf, " @ %client.namebase @ " is " @ %realname @ "."); + } + } + else + { + messageClient(%sender, '', "\c2Smurf, " @ %client.namebase @ " is " @ %realname @ "."); + } + } +} +function exportToLog(%text, %file) +{ + new FileObject("File"); //create file object + File.openForAppend(%file); //open it up, and create it if it isn't there + File.writeLine(%text); //write the text that we want + File.close(); //close the file + File.delete(); //delete the object (not the file) +} + +function dismountPlayers() +{ + // make sure all palyers are dismounted from vehicles and have normal huds + %count = ClientGroup.getCount(); + for(%cl = 0; %cl < %count; %cl++) + { + %client = ClientGroup.getObject(%cl); + %player = %client.player; + if (%player.isMounted()) { + %player.unmount(); + commandToClient(%client, 'setHudMode', 'Standard', "", 0); + } + } +} + +function loadMission( %missionName, %missionType, %firstMission ) +{ + //ensure the demo server is using appropriate missions + if (isDemo() && %missionType !$= "SinglePlayer") + { + if (%missionName $= "Slapdash") + %missionType = "CTF"; + else if (%missionName $= "Rasp") + %missionType = "Hunters"; + else + { + %missionName = "Slapdash"; + %missionType = "CTF"; + } + } + + // TR2 + // TR2 is scaled, so we need to increase the camera speed. However, we also + // need to set it back to the default for other game types. + if( %missionType $= "TR2" ) + { + $_Camera::movementSpeed = $Camera::movementSpeed; + $Camera::movementSpeed = 80; + } + else + { + %val = $_Camera::movementSpeed $= "" ? 40 : $_Camera::movementSpeed; + $Camera::movementSpeed = %val; + } + + $LoadingMission = true; + disableCyclingConnections(true); + if (!$pref::NoClearConsole) + cls(); + if ( isObject( LoadingGui ) ) + LoadingGui.gotLoadInfo = ""; + buildLoadInfo( %missionName, %missionType ); + + // reset all of these + ClearCenterPrintAll(); + ClearBottomPrintAll(); + + if( !isDemo() && $Host::TournamentMode ) + resetTournamentPlayers(); + + // Send load info to all the connected clients: + %count = ClientGroup.getCount(); + for ( %cl = 0; %cl < %count; %cl++ ) + { + %client = ClientGroup.getObject( %cl ); + if ( !%client.isAIControlled() ) + sendLoadInfoToClient( %client ); + } + + // allow load condition to exit out + schedule(0,ServerGroup,loadMissionStage1,%missionName,%missionType,%firstMission); +} + +function loadMissionStage1(%missionName, %missionType, %firstMission) +{ + // if a mission group was there, delete prior mission stuff + if (isObject(MissionGroup)) + { + // clear out the previous mission paths + for(%clientIndex = 0; %clientIndex < ClientGroup.getCount(); %clientIndex++) + { + // clear ghosts and paths from all clients + %cl = ClientGroup.getObject(%clientIndex); + %cl.resetGhosting(); + %cl.clearPaths(); + %cl.isReady = ""; + %cl.matchStartReady = false; + } + Game.endMission(); + $lastMissionTeamCount = Game.numTeams; + + MissionGroup.delete(); + MissionCleanup.delete(); + Game.deactivatePackages(); + Game.delete(); + $ServerGroup.delete(); + $ServerGroup = new SimGroup(ServerGroup); + } + + $CurrentMission = %missionName; + $CurrentMissionType = %missionType; + + createInvBanCount(); + echo("LOADING MISSION: " @ %missionName); + + // increment the mission sequence (used for ghost sequencing) + $missionSequence++; + + // if this isn't the first mission, allow some time for the server + // to transmit information to the clients: + +// jff: $currentMission already being used for this purpose, used in 'finishLoadMission' + $MissionName = %missionName; + $missionRunning = false; + + if (!%firstMission) + schedule(15000, ServerGroup, loadMissionStage2); + else + loadMissionStage2(); +} + + +function loadMissionStage2() +{ + // create the mission group off the ServerGroup + echo("Stage 2 load"); + $instantGroup = ServerGroup; + + new SimGroup (MissionCleanup); + + if ($EnergizeLoop != 1) + StartEnergizeLoop(); + + if ($CurrentMissionType $= "") + { + new ScriptObject(Game) { + class = DefaultGame; + }; + } + else + { + new ScriptObject(Game) { + class = $CurrentMissionType @ "Game"; + superClass = DefaultGame; + }; + } + // allow the game to activate any packages. + Game.activatePackages(); + + // reset the target manager + resetTargetManager(); + + %file = "missions/" @ $missionName @ ".mis"; + if (!isFile(%file)) + return; + + // send the mission file crc to the clients (used for mission lighting) + $missionCRC = getFileCRC(%file); + %count = ClientGroup.getCount(); + for(%i = 0; %i < %count; %i++) + { + %client = ClientGroup.getObject(%i); + if (!%client.isAIControlled()) + %client.setMissionCRC($missionCRC); + } + + // clear the power list + $PowerList = ""; + + $countDownStarted = false; + exec(%file); + $instantGroup = MissionCleanup; + + if ($Host::Prison::Enabled == 1) + prisonEnable(); + else + $Host::Prison::Enabled = 0; + + // pre-game mission stuff + if (!isObject(MissionGroup)) + { + error("No 'MissionGroup' found in mission \"" @ $missionName @ "\"."); + schedule(3000, ServerGroup, CycleMissions); + return; + } + + MissionGroup.cleanNonType($CurrentMissionType); + + // construct paths + pathOnMissionLoadDone(); + + $ReadyCount = 0; + $MatchStarted = false; + $CountdownStarted = false; + AISystemEnabled( false ); + + // Set the team damage here so that the game type can override it: + if ( isDemo() ) + $TeamDamage = 0; + else if ( $Host::TournamentMode ) + $TeamDamage = 1; + else + $TeamDamage = $Host::TeamDamageOn; + + //the demo version always has team damage off + if (isDemo()) + $TeamDamage = 0; + + // z0dd - ZOD, 10/06/02. Reset $InvincibleTime to defaults. + if(Game.class !$= TR2Game) + $InvincibleTime = 6; + + // Velocity limiter + limitVelocityLoop(); + + // Killer fog + if (MissionArea.killerFogAlt !$= "" && MissionArea.killerFogAlt != 0) + killerFog(); + + Game.missionLoadDone(); + + // start all the clients in the mission + $missionRunning = true; + for(%clientIndex = 0; %clientIndex < ClientGroup.getCount(); %clientIndex++) + ClientGroup.getObject(%clientIndex).startMission(); + + if ($Host::Purebuild == 1) + purebuildOn(); + else + purebuildOff(); + + if ($Host::Cascade !$= "0" && $Host::Cascade != 1) + $Host::Cascade = 1; + + if ($Host::Vehicles $= "0") + disableVehicles(); + else + enableVehicles(); + + if ($Host::Nerf::Enabled $= "0") + nerfDisable(); + else + nerfEnable(); + + if ($Host::Hazard::Enabled == 1) + hazardOn(); + else + hazardOff(); + + if ($Host::InvincibleArmors != 1) + $Host::InvincibleArmors = 0; + + if ($Host::InvincibleDeployables != 1) + $Host::InvincibleDeployables = 0; + + if ($Host::SatchelChargeEnabled !$= "0") + $Host::SatchelChargeEnabled = 1; + + if ($Host::MTC::Enabled == 1) + startMTC(); + else + stopMTC(); + + if ($Host::OnlyOwnerDeconstruct != 1) + $Host::OnlyOwnerDeconstruct = 0; + if ($Host::OnlyOwnerCascade != 1) + $Host::OnlyOwnerCascade = 0; + if ($Host::OnlyOwnerRotate != 1) + $Host::OnlyOwnerRotate = 0; + if ($Host::OnlyOwnerCubicReplace != 1) + $Host::OnlyOwnerCubicReplace = 0; + + if ($Host::AllowUnderground != 1) + $Host::AllowUnderground = 0; + + if ($Host::RepairPatchOnDeath != 1) + $Host::RepairPatchOnDeath = 0; + + if ($Host::ExpertMode == 1) + expertModeOn(); + else + expertModeOff(); + + if (!$MatchStarted && $LaunchMode !$= "NavBuild" && $LaunchMode !$= "SpnBuild" ) + { + if ( !isDemo() && $Host::TournamentMode ) + checkTourneyMatchStart(); + else if ( $currentMissionType !$= "SinglePlayer" ) + checkMissionStart(); + } + + // offline graph builder... + if ( $LaunchMode $= "NavBuild" ) + buildNavigationGraph( "Nav" ); + + if ( $LaunchMode $= "SpnBuild" ) + buildNavigationGraph( "Spn" ); + purgeResources(); + disableCyclingConnections(false); + $LoadingMission = false; +} + + +function ShapeBase::cleanNonType(%this, %type) +{ + if (%this.missionTypesList $= "") + return; + + for(%i = 0; (%typei = getWord(%this.missionTypesList, %i)) !$= ""; %i++) + if (%typei $= %type) + return; + + // first 32 targets are team targets (never allocated/freed) + // - must reallocate the target if unhiding + if (%this.getTarget() >= 32) + { + freeTarget(%this.getTarget()); + %this.setTarget(-1); + } + + %this.hide(true); +} + +function SimObject::cleanNonType(%this, %type) +{ +} + +function SimGroup::cleanNonType(%this, %type) +{ + for (%i = 0; %i < %this.getCount(); %i++) + %this.getObject(%i).cleanNonType(%type); +} + +function GameConnection::endMission(%this) +{ + commandToClient(%this, 'MissionEnd', $missionSequence); +} + +//-------------------------------------------------------------------------- +// client start phases: +// 0: start mission +// 1: got phase1 done +// 2: got datablocks done +// 3: got phase2 done +// 4: got phase3 done +function GameConnection::startMission(%this) +{ + // send over the information that will display the server info + // when we learn it got there, we'll send the data blocks + %this.currentPhase = 0; + commandToClient(%this, 'MissionStartPhase1', $missionSequence, $MissionName, MissionGroup.musicTrack); +} + +function serverCmdMissionStartPhase1Done(%client, %seq) +{ + if (%seq != $missionSequence || !$MissionRunning) + return; + + if (%client.currentPhase != 0) + return; + %client.currentPhase = 1; + + // when the datablocks are transmitted, we'll send the ghost always objects + %client.transmitDataBlocks($missionSequence); +} + +function GameConnection::dataBlocksDone( %client, %missionSequence ) +{ + echo("GOT DATA BLOCKS DONE FOR: " @ %client); + if (%missionSequence != $missionSequence) + return; + + if (%client.currentPhase != 1) + return; + %client.currentPhase = 2; + + // only want to set this once... (targets will not be updated/sent until a + // client has this flag set) + if (!%client.getReceivedDataBlocks()) + { + %client.setReceivedDataBlocks(true); + sendTargetsToClient(%client); + } + + commandToClient(%client, 'MissionStartPhase2', $missionSequence); +} + +function serverCmdMissionStartPhase2Done(%client, %seq) +{ + if (%seq != $missionSequence || !$MissionRunning) + return; + + if (%client.currentPhase != 2) + return; + %client.currentPhase = 3; + + // when all this good love is over, we'll know that the mission lighting is done + %client.transmitPaths(); + + // setup the client team state + if ( $CurrentMissionType !$= "SinglePlayer" ) + serverSetClientTeamState( %client ); + + // start ghosting + %client.activateGhosting(); + %client.camera.scopeToClient(%client); + + // to the next phase... + commandToClient(%client, 'MissionStartPhase3', $missionSequence, $CurrentMission); +} + +function serverCmdMissionStartPhase3Done(%client, %seq) +{ + if (%seq != $missionSequence || !$MissionRunning) + return; + + if (%client.currentPhase != 3) + return; + %client.currentPhase = 4; + + %client.isReady = true; + Game.clientMissionDropReady(%client); +} + +function serverSetClientTeamState( %client ) +{ + // set all player states prior to mission drop ready + + // create a new camera for this client + %client.camera = new Camera() + { + dataBlock = Observer; + }; + + if ( isObject( %client.rescheduleVote ) ) + Cancel( %client.rescheduleVote ); + %client.canVote = true; + %client.rescheduleVote = ""; + + MissionCleanup.add( %client.camera ); // we get automatic cleanup this way. + + %observer = false; + if ( isDemo() || !$Host::TournamentMode ) + { + if ( %client.justConnected ) + { + %client.justConnected = false; + %client.camera.getDataBlock().setMode( %client.camera, "justJoined" ); + } + else + { + // server just changed maps - this guy was here before + if ( %client.lastTeam !$= "" ) + { + // see if this guy was an observer from last game + if (%client.lastTeam == 0) + { + %observer = true; + + %client.camera.getDataBlock().setMode( %client.camera, "ObserverFly" ); + } + else // let this player join the team he was on last game + { + if (Game.numTeams > 1 && %client.lastTeam <= Game.numTeams ) + { + Game.clientJoinTeam( %client, %client.lastTeam, false ); + } + else + { + Game.assignClientTeam( %client ); + + // spawn the player + Game.spawnPlayer( %client, false ); + } + } + } + else + { + Game.assignClientTeam( %client ); + + // spawn the player + Game.spawnPlayer( %client, false ); + } + + if ( !%observer ) + { + if (!$MatchStarted && !$CountdownStarted) + %client.camera.getDataBlock().setMode( %client.camera, "pre-game", %client.player ); + else if (!$MatchStarted && $CountdownStarted) + %client.camera.getDataBlock().setMode( %client.camera, "pre-game", %client.player ); + } + } + } + else + { + // don't need to do anything. MissionDrop will handle things from here. + } +} + +//function serverCmdPreviewDropReady( %client ) +//{ +// $MatchStarted = true; +// commandToClient( %client, 'SetMoveKeys', true); +// %markerObj = "0 0 0"; +// %client.camera.mode = "PreviewMode"; +// %client.camera.setTransform( %markerObj ); +// %client.camera.setFlyMode(); +// +// %client.setControlObject( %client.camera ); +//} + +function HideHudHACK(%visible) +{ + //compassHud.setVisible(%visible); + //enerDamgHud.setVisible(%visible); + retCenterHud.setVisible(%visible); + reticleFrameHud.setVisible(%visible); + //invPackHud.setVisible(%visible); + weaponsHud.setVisible(%visible); + outerChatHud.setVisible(%visible); + objectiveHud.setVisible(%visible); + chatHud.setVisible(%visible); + navHud.setVisible(%visible); + //watermarkHud.setVisible(%visible); + hudClusterBack.setVisible(%visible); + inventoryHud.setVisible(%visible); + clockHUD.setVisible(%visible); +} + +function ServerPlay2D(%profile) +{ + for(%idx = 0; %idx < ClientGroup.getCount(); %idx++) + ClientGroup.getObject(%idx).play2D(%profile); +} + +function ServerPlay3D(%profile,%transform) +{ + for(%idx = 0; %idx < ClientGroup.getCount(); %idx++) + ClientGroup.getObject(%idx).play3D(%profile,%transform); +} + +function clientCmdSetFirstPerson(%value) +{ + $firstPerson = %value; + if (%value) + ammoHud.setVisible(true); + else + ammoHud.setVisible(false); +} + +function clientCmdGetFirstPerson() +{ + commandToServer('FirstPersonValue', $firstPerson); +} + +function serverCmdFirstPersonValue(%client, %firstPerson) +{ + %client.player.firstPerson = %firstPerson; +} + +function clientCmdVehicleMount() +{ + if ( $pref::toggleVehicleView ) + { + $wasFirstPerson = $firstPerson; + $firstPerson = false; + } +} + +function clientCmdVehicleDismount() +{ + if ( $pref::toggleVehicleView ) + $firstPerson = $wasFirstPerson; +} + +function serverCmdSAD( %client, %password ) +{ + if ( %password !$= "" && %password $= $Host::AdminPassword) + { + %client.isAdmin = true; + %client.isSuperAdmin = true; + %name = getTaggedString( %client.name ); + MessageAll( 'MsgSuperAdminPlayer', '\c2%2 has become a Super Admin by force.', %client, %client.name ); + } +} + +function serverCmdSADSetPassword(%client, %password) +{ + // ----------------------------------------------------- + // z0dd - ZOD, 5/8/02. Addition. Have to export or it won't stick. + //if(%client.isSuperAdmin) + // $Host::AdminPassword = %password; + + if(%client.isSuperAdmin) + { + $Host::AdminPassword = %password; + export( "$Host::*", "prefs/ServerPrefs.cs", false ); + messageClient(%client, 'MsgAdmin', '\c2\"Super Admin\" PW changed to: \c3%1\c2.', %password); + logEcho(getTaggedString(%client.name) @ " changed Super Admin password to: " @ %password); + } +} + +function serverCmdSuicide(%client) +{ + // ------------------------------------- + // z0dd - ZOD, 5/8/02. Addition. Console spam fix. + if(!isObject(%client.player)) + return; + + if ( $MatchStarted && !%client.isJailed) + %client.player.scriptKill($DamageType::Suicide); +} + +function serverCmdToggleCamera(%client) +{ + if ($testcheats || $CurrentMissionType $= "SinglePlayer") + { + %control = %client.getControlObject(); + if (%control == %client.player) + { + %control = %client.camera; + %control.mode = toggleCameraFly; + %control.setFlyMode(); + } + else + { + %control = %client.player; + %control.mode = observerFly; + %control.setFlyMode(); + } + %client.setControlObject(%control); + } +} + +function serverCmdDropPlayerAtCamera(%client) +{ + if ($testcheats) + { + %client.player.setTransform(%client.camera.getTransform()); + %client.player.setVelocity("0 0 0"); + %client.setControlObject(%client.player); + } +} + +function serverCmdDropCameraAtPlayer(%client) +{ + if ($testcheats) + { + %client.camera.setTransform(%client.player.getTransform()); + %client.camera.setVelocity("0 0 0"); + %client.setControlObject(%client.camera); + } +} + +function serverCmdToggleRace(%client) +{ + if ($testcheats) + { + if (%client.race $= "Human") + %client.race = "Bioderm"; + else + %client.race = "Human"; + %client.player.setArmor(%client.armor); + } +} + +function serverCmdToggleGender(%client) +{ + if ($testcheats) + { + if (%client.sex $= "Male") + %client.sex = "Female"; + else + %client.sex = "Male"; + %client.player.setArmor(%client.armor); + } +} + +function serverCmdToggleArmor(%client) +{ + if ($testcheats) + { + if (%client.armor $= "Light") + %client.armor = "Medium"; + else + if (%client.armor $= "Medium") + %client.armor = "Heavy"; + else + %client.armor = "Light"; + %client.player.setArmor(%client.armor); + } +} + +function serverCmdPlayCel(%client,%anim) +{ + if ($testcheats) + { + %anim = %client.player.celIdx; + if (%anim++ > 8) + %anim = 1; + %client.player.setActionThread("cel"@%anim); + %client.player.celIdx = %anim; + } +} + +// NOTENOTENOTE: Review +function serverCmdPlayAnim(%client, %anim) +{ + if ( %anim $= "Death1" || %anim $= "Death2" || %anim $= "Death3" || %anim $= "Death4" || %anim $= "Death5" || + %anim $= "Death6" || %anim $= "Death7" || %anim $= "Death8" || %anim $= "Death9" || %anim $= "Death10" || %anim $= "Death11" ) + return; + + %player = %client.player; + // don't play animations if player is in a vehicle + // ------------------------------------------------------------------ + // z0dd - ZOD, 5/8/02. Console spam fix, check for player object too. + //if (%player.isMounted()) + // return; + if(!isObject(%player)) + return; + + if(%player.isMounted()) // JTL :P + return; + + %weapon = ( %player.getMountedImage($WeaponSlot) == 0 ) ? "" : %player.getMountedImage($WeaponSlot).getName().item; + if (%weapon $= "MissileLauncher" || %weapon $= "SniperRifle") + { + %player.animResetWeapon = true; + %player.lastWeapon = %weapon; + %player.unmountImage($WeaponSlot); + // ---------------------------------------------- + // z0dd - ZOD, 5/8/02. %obj is the wrong varible. + //%obj.setArmThread(look); + %player.setArmThread(look); + } + %player.setActionThread(%anim); +} + +function serverCmdPlayDeath(%client,%anim) +{ + if ($testcheats) + { + %anim = %client.player.deathIdx; + if (%anim++ > 11) + %anim = 1; + %client.player.setActionThread("death"@%anim,true); + %client.player.deathIdx = %anim; + } +} + +// NOTENOTENOTE: Review these! +//------------------------------------------------------------ +// TODO - make this function specify a team to switch to... +function serverCmdClientTeamChange( %client ) +{ + // pass this to the game object to handle: + if ( isObject( Game ) && Game.kickClient != %client && !%client.isJailed) + { + %fromObs = %client.team == 0; + + if (%fromObs) + clearBottomPrint(%client); + + Game.clientChangeTeam( %client, "", %fromObs ); + } +} + +function serverCanAddBot() +{ + //find out how many bots are already playing + %botCount = 0; + %numClients = ClientGroup.getCount(); + for (%i = 0; %i < %numClients; %i++) + { + %cl = ClientGroup.getObject(%i); + if (%cl.isAIcontrolled()) + %botCount++; + } + + //add only if we have less bots than the bot count, and if there would still be room for a + if ($HostGameBotCount > 0 && %botCount < $Host::botCount && %numClients < $Host::maxPlayers - 1) + return true; + else + return false; +} + +function serverCmdAddBot( %client ) +{ + //only admins can add bots... + if (%client.isAdmin || %client.isSuperAdmin) + { + if (serverCanAddBot()) + aiConnectMultiple( 1, $Host::MinBotDifficulty, $Host::MaxBotDifficulty, -1 ); + } +} + +function serverCmdClientJoinTeam( %client, %team ) +{ + if ( %team == -1 ) + { + if ( %client.team == 1 ) + %team = 2; + else + %team = 1; + } + + if (!(%client.isAdmin || %client.isSuperAdmin || %client.isAIControlled())) { + if (%team > Game.numTeams || %team $= "") + %team = 1; + } + + if ( isObject( Game ) && Game.kickClient != %client && !%client.isJailed) + { + if (%client.team != %team) + { + %fromObs = %client.team == 0; + + if (%fromObs) + clearBottomPrint(%client); + + if ( %client.isAIControlled() ) + Game.AIChangeTeam( %client, %team ); + else + Game.clientChangeTeam( %client, %team, %fromObs ); + } + } +} + +// this should only happen in single team games +function serverCmdClientAddToGame( %client, %targetClient ) +{ + if (!(%client.isAdmin || %client.isSuperAdmin)) + return; + + if ( isObject( Game ) ) + Game.clientJoinTeam( %targetClient, 0, $matchstarted ); + + clearBottomPrint(%targetClient); + + if ($matchstarted) + { + %targetClient.setControlObject( %targetClient.player ); + commandToClient(%targetClient, 'setHudMode', 'Standard'); + } + else + { + %targetClient.notReady = true; + %targetClient.camera.getDataBlock().setMode( %targetClient.camera, "pre-game", %targetClient.player ); + %targetClient.setControlObject( %targetClient.camera ); + } + + if ( !isDemo() && $Host::TournamentMode && !$CountdownStarted) + { + %targetClient.notReady = true; + centerprint( %targetClient, "\nPress FIRE when ready.", 0, 3 ); + } +} + +function serverCmdClientJoinGame( %client ) +{ + if ( isObject( Game ) ) + Game.clientJoinTeam( %client, 0, 1 ); + + %client.setControlObject( %client.player ); + clearBottomPrint(%client); + commandToClient(%client, 'setHudMode', 'Standard'); +} + +function serverCmdClientMakeObserver( %client ) +{ + if ( isObject( Game ) && Game.kickClient != %client && !%client.isJailed) + Game.forceObserver( %client, "playerChoose" ); +} + +function serverCmdChangePlayersTeam( %clientRequesting, %client, %team) +{ + if ( isObject( Game ) && %client != Game.kickClient && (%clientRequesting.isAdmin || %clientRequesting.isSuperAdmin)) + { + serverCmdClientJoinTeam(%client, %team); + + if (!$MatchStarted) + { + %client.observerMode = "pregame"; + %client.notReady = true; + %client.camera.getDataBlock().setMode( %client.camera, "pre-game", %client.player ); + %client.setControlObject( %client.camera ); + + if ( !isDemo() && $Host::TournamentMode && !$CountdownStarted) + { + %client.notReady = true; + centerprint( %client, "\nPress FIRE when ready.", 0, 3 ); + } + } + else + commandToClient(%client, 'setHudMode', 'Standard', "", 0); + + %multiTeam = (Game.numTeams > 1); + if (%multiTeam) + { + messageClient( %client, 'MsgClient', '\c1The Admin has changed your team.'); + messageAllExcept( %client, -1, 'MsgClient', '\c1The Admin forced %1 to join the %2 team.', %client.name, game.getTeamName(%client.team) ); + } + else + { + messageClient( %client, 'MsgClient', '\c1The Admin has added you to the game.'); + messageAllExcept( %client, -1, 'MsgClient', '\c1The Admin added %1 to the game.', %client.name); + } + } +} + +function serverCmdForcePlayerToObserver( %clientRequesting, %client ) +{ + if ( isObject( Game ) && (%clientRequesting.isAdmin || %clientRequesting.isSuperAdmin)) + Game.forceObserver( %client, "adminForce" ); +} + +//-------------------------------------------------------------------------- + +function serverCmdTogglePlayerMute(%client, %who) +{ + if (%client.muted[%who]) + { + %client.muted[%who] = false; + messageClient(%client, 'MsgPlayerMuted', '%1 has been unmuted.', %who.name, %who, false); + } + else + { + %client.muted[%who] = true; + messageClient(%client, 'MsgPlayerMuted', '%1 has been muted.', %who.name, %who, true); + } +} + +//-------------------------------------------------------------------------- +// VOTE MENU FUNCTIONS: +function serverCmdGetVoteMenu( %client, %key ) +{ + if ( isObject( Game ) ) + Game.sendGameVoteMenu( %client, %key ); +} + +function serverCmdGetPlayerPopupMenu( %client, %targetClient, %key ) +{ + if ( isObject( Game ) ) + Game.sendGamePlayerPopupMenu( %client, %targetClient, %key ); +} + +function serverCmdGetTeamList( %client, %key ) +{ + if ( isObject( Game ) ) + Game.sendGameTeamList( %client, %key ); +} + +function serverCmdGetMissionTypes( %client, %key ) { + for ( %type = 0; %type < $HostTypeCount; %type++ ) + messageClient( %client, 'MsgVoteItem', "", %key, %type, "", $HostTypeDisplayName[%type], true ); + if (%client.isAdmin || %client.isSuperAdmin) + messageClient( %client, 'MsgVoteItem', "", %key, "LoadBuildingFile", "", " - Load Building File - ", true ); +} + +function serverCmdGetMissionList( %client, %key, %type ) { + if ( %type < 0 || %type >= $HostTypeCount ) + return; + + if (%type $= "LoadBuildingFile" && (%client.isAdmin || %client.isSuperAdmin)) { + %dir = "Buildings/Admin/"; + %idx = 0; + for(%file = findFirstFile(%dir @ "*.cs"); %file !$= ""; %file = findNextFile(%dir @ "*.cs")) { + messageClient(%client,'MsgVoteItem',"",%key,%idx++,"",getSubStr(%file,strLen(%dir),strLen(%file)-strLen(%dir)),true); + } + %dir = $SaveBuilding::AutoSaveFolder; + %buildingCount = 0; + for (%index = 0;%index < 11;%index++) + $SaveBuilding::Found[%index] = ""; + for (%found = true;%found;%buildingCount++ ) { + %suffix = %buildingCount; + while (strLen(%suffix) < 5) %suffix = "0" @ %suffix; + %file = $SaveBuilding::AutoSaveFolder @ $MissionName @ "-" @ %suffix @ ".cs"; + if (%found = isFile(%file)) { + for (%index = 10;%index > 0;%index--) { + $SaveBuilding::Found[%index] = $SaveBuilding::Found[%index - 1]; + } + $SaveBuilding::Found[0] = %file; + } + + } + for (%index = 0;%index < 11;%index++) { + %file = $SaveBuilding::Found[%index]; + if (%file !$= "") + messageClient(%client,'MsgVoteItem',"",%key,%idx++,"","_" @ getSubStr(%file,strLen(%dir),strLen(%file)-strLen(%dir)),true); + } + + } + + for ( %i = $HostMissionCount[%type] - 1; %i >= 0; %i-- ) { + %idx = $HostMission[%type, %i]; + + // If we have bots, don't change to a mission that doesn't support bots: + if ( $HostGameBotCount > 0 ) { + if ( !$BotEnabled[%idx] ) + continue; + } + + messageClient( %client, 'MsgVoteItem', "", %key, + %idx, // mission index, will be stored in $clVoteCmd + "", + $HostMissionName[%idx], + true ); + } +} + +function serverCmdGetTimeLimitList( %client, %key, %type ) +{ + if ( isObject( Game ) ) + Game.sendTimeLimitList( %client, %key ); +} + +function serverCmdClientPickedTeam( %client, %option ) +{ + if (!$Host::TournamentMode) + return; + + if (!(%client.isAdmin || %client.isSuperAdmin)) { + if (%option > Game.numTeams || %option $= "") + %option = 1; + } + + // ------------------------------------------------------------------------------------ + // z0dd - ZOD 5/8/02. Tourney mode bug fix provided by FSB-AO. + // Bug description: In tournament mode, If a player is teamchanged by an admin before + // they select a team, the server just changes their team and re-skins the player. They + // are not moved from their initial spawn point, meaning they could spawn very close to + // the other teams flag. This script kills the player if they are already teamed when + // they select an option and spawns them on the correct side of the map. + + //if( %option == 1 || %option == 2 ) + // Game.clientJoinTeam( %client, %option, false ); + + //else if( %option == 3) + //{ + // Game.assignClientTeam( %client, $MatchStarted ); + // Game.spawnPlayer( %client, false ); + //} + //else + //{ + // Game.forceObserver( %client, "playerChoose" ); + // %client.observerMode = "observer"; + // %client.notReady = false; + // return; + //} + switch(%option) + { + case 1: + if ( isObject(%client.player) ) + { + %client.player.scriptKill(0); + Game.clientChangeTeam(%client, %option, 0); + } + else + Game.clientJoinTeam( %client, %option, false ); + case 2: + if ( isObject(%client.player) ) + { + %client.player.scriptKill(0); + Game.clientChangeTeam(%client, %option, 0); + } + else + Game.clientJoinTeam( %client, %option, false ); + case 3: + if( !isObject(%client.player) ) + { + Game.assignClientTeam( %client, $MatchStarted ); + Game.spawnPlayer( %client, false ); + } + default: + if( isObject(%client.player) ) + { + %client.player.scriptKill(0); + ClearBottomPrint(%client); + } + Game.forceObserver( %client, "playerChoose" ); + %client.observerMode = "observer"; + %client.notReady = false; + return; + } + // End z0dd - ZOD + // ------------------------------------------------------------------------------------ + ClearBottomPrint(%client); + %client.observerMode = "pregame"; + %client.notReady = true; + %client.camera.getDataBlock().setMode( %client.camera, "pre-game", %client.player ); + commandToClient(%client, 'setHudMode', 'Observer'); + + + %client.setControlObject( %client.camera ); + centerprint( %client, "\nPress FIRE when ready.", 0, 3 ); +} + +function playerPickTeam( %client ) +{ + %numTeams = Game.numTeams; + + if (%numTeams > 1) + { + %client.camera.mode = "PickingTeam"; + schedule( 0, 0, "commandToClient", %client, 'pickTeamMenu', Game.getTeamName(1), Game.getTeamName(2)); + } + else + { + Game.clientJoinTeam(%client, 0, 0); + %client.observerMode = "pregame"; + %client.notReady = true; + %client.camera.getDataBlock().setMode( %client.camera, "pre-game", %client.player ); + centerprint( %client, "\nPress FIRE when ready.", 0, 3 ); + %client.setControlObject( %client.camera ); + } +} + +function serverCmdPlayContentSet( %client ) +{ + if ( !isDemo() && $Host::TournamentMode && !$CountdownStarted && !$MatchStarted ) + playerPickTeam( %client ); +} + +//-------------------------------------------------------------------------- +// This will probably move elsewhere... +function getServerStatusString() +{ + return isObject(Game) ? Game.getServerStatusString() : "NoGame"; +} + + +function dumpGameString() +{ + error( getServerStatusString() ); +} + +function isOnAdminList(%client) +{ + if ( !%totalRecords = getFieldCount( $Host::AdminList ) ) + { + return false; + } + + for(%i = 0; %i < %totalRecords; %i++) + { + %record = getField( getRecord( $Host::AdminList, 0 ), %i); + if (%record == %client.guid) + return true; + } + + return false; +} + +function isOnSuperAdminList(%client) +{ + if ( !%totalRecords = getFieldCount( $Host::superAdminList ) ) + { + return false; + } + + for(%i = 0; %i < %totalRecords; %i++) + { + %record = getField( getRecord( $Host::superAdminList, 0 ), %i); + if (%record == %client.guid) + return true; + } + + return false; +} + +function ServerCmdAddToAdminList( %admin, %client ) +{ + if ( !%admin.isSuperAdmin ) + return; + + %count = getFieldCount( $Host::AdminList ); + + for ( %i = 0; %i < %count; %i++ ) + { + %id = getField( $Host::AdminList, %i ); + if ( %id == %client.guid ) + { + return; // They're already there! + } + } + + if ( %count == 0 ) + $Host::AdminList = %client.guid; + else + $Host::AdminList = $Host::AdminList TAB %client.guid; + + // --------------------------------------------------------------------------------------------------------------------------- + // z0dd - ZOD, 5/8/02. Addition. Was not exporting to serverPrefs and did not message admin status. + export( "$Host::*", "prefs/ServerPrefs.cs", false ); + messageClient(%admin, 'MsgAdmin', '\c3\"%1\"\c2 added to Admin list: \c3%2\c2.', getTaggedString(%client.name), %client.guid); + logEcho(getTaggedString(%admin.name) @ " added " @ getTaggedString(%client.name) @ " " @ %client.guid @ " to Admin list."); +} + +function ServerCmdAddToSuperAdminList( %admin, %client ) +{ + if ( !%admin.isSuperAdmin ) + return; + + %count = getFieldCount( $Host::SuperAdminList ); + + for ( %i = 0; %i < %count; %i++ ) + { + %id = getField( $Host::SuperAdminList, %i ); + if ( %id == %client.guid ) + return; // They're already there! + } + + if ( %count == 0 ) + $Host::SuperAdminList = %client.guid; + else + $Host::SuperAdminList = $Host::SuperAdminList TAB %client.guid; + + // --------------------------------------------------------------------------------------------------------------------------------- + // z0dd - ZOD, 5/8/02. Addition. Was not exporting to serverPrefs and did not message admin status. + export( "$Host::*", "prefs/ServerPrefs.cs", false ); + messageClient(%admin, 'MsgAdmin', '\c3\"%1\"\c2 added to Super Admin list: \c3%2\c2.', getTaggedString(%client.name), %client.guid); + logEcho(getTaggedString(%admin.name) @ " added " @ getTaggedString(%client.name) @ " " @ %client.guid @ " to Super Admin list."); +} + +function resetTournamentPlayers() +{ + %count = ClientGroup.getCount(); + for( %i = 0; %i < %count; %i++ ) + { + %cl = ClientGroup.getObject(%i); + %cl.notready = 1; + %cl.notReadyCount = ""; + } +} + +function forceTourneyMatchStart() +{ + %playerCount = 0; + %count = ClientGroup.getCount(); + for( %i = 0; %i < %count; %i++ ) + { + %cl = ClientGroup.getObject(%i); + if (%cl.camera.Mode $= "pre-game") + %playerCount++; + } + + // don't start the mission until we have players + if (%playerCount == 0) + { + return false; + } + + %count = ClientGroup.getCount(); + for( %i = 0; %i < %count; %i++ ) + { + %cl = ClientGroup.getObject(%i); + if (%cl.camera.Mode $= "pickingTeam") + { + // throw these guys into observer mode + if (Game.numTeams > 1) + commandToClient( %cl, 'processPickTeam'); // clear the pickteam menu + Game.forceObserver( %cl, "adminForce" ); + } + } + return true; +} + +function startTourneyCountdown() +{ + %count = ClientGroup.getCount(); + for( %i = 0; %i < %count; %i++ ) + { + %cl = ClientGroup.getObject(%i); + ClearCenterPrint(%cl); + ClearBottomPrint(%cl); + } + + // lets get it on! + Countdown( 30 * 1000 ); +} + +function checkTourneyMatchStart() +{ + if ( $CountdownStarted || $matchStarted ) + return; + + // loop through all the clients and see if any are still notready + %playerCount = 0; + %notReadyCount = 0; + + %count = ClientGroup.getCount(); + for( %i = 0; %i < %count; %i++ ) + { + %cl = ClientGroup.getObject(%i); + if (%cl.camera.mode $= "pickingTeam") + { + %notReady[%notReadyCount] = %cl; + %notReadyCount++; + } + else if (%cl.camera.Mode $= "pre-game") + { + if (%cl.notready) + { + %notReady[%notReadyCount] = %cl; + %notReadyCount++; + } + else + { + %playerCount++; + } + } + else if (%cl.camera.Mode $= "observer") + { + // this guy is watching + } + } + + if (%notReadyCount) + { + if (%notReadyCount == 1) + MessageAll( 'msgHoldingUp', '\c1%1 is holding things up!', %notReady[0].name); + else if (%notReadyCount < 4) + { + for(%i = 0; %i < %notReadyCount - 2; %i++) + %str = getTaggedString(%notReady[%i].name) @ ", " @ %str; + + %str = "\c2" @ %str @ getTaggedString(%notReady[%i].name) @ " and " @ getTaggedString(%notReady[%i+1].name) + @ " are holding things up!"; + MessageAll( 'msgHoldingUp', %str ); + } + return; + } + + if (%playerCount != 0) + { + %count = ClientGroup.getCount(); + for( %i = 0; %i < %count; %i++ ) + { + %cl = ClientGroup.getObject(%i); + %cl.notready = ""; + %cl.notReadyCount = ""; + ClearCenterPrint(%cl); + ClearBottomPrint(%cl); + } + + if ( Game.scheduleVote !$= "" && Game.voteType $= "VoteMatchStart") + { + messageAll('closeVoteHud', ""); + cancel(Game.scheduleVote); + Game.scheduleVote = ""; + } + + Countdown(30 * 1000); + } +} + +function checkMissionStart() +{ + %readyToStart = false; + for(%clientIndex = 0; %clientIndex < ClientGroup.getCount(); %clientIndex++) + { + %client = ClientGroup.getObject(%clientIndex); + if (%client.isReady) + { + %readyToStart = true; + break; + } + } + + if (%readyToStart || ClientGroup.getCount() < 1) + { + if ($Host::warmupTime > 0 && $CurrentMissionType !$= "SinglePlayer") + countDown($Host::warmupTime * 1000); + else + Game.startMatch(); + + for(%x = 0; %x < $NumVehiclesDeploy; %x++) + $VehiclesDeploy[%x].getDataBlock().schedule(%timeMS / 2, "vehicleDeploy", $VehiclesDeploy[%x], 0, 1); + $NumVehiclesDeploy = 0; + } + else + { + schedule(2000, ServerGroup, "checkMissionStart"); + } +} + +function Countdown(%timeMS) +{ + if ($countdownStarted) + return; + + echo("starting mission countdown..."); + + if (isObject(Game)) + %game = Game.getId(); + else + return; + + $countdownStarted = true; + Game.matchStart = Game.schedule( %timeMS, "StartMatch" ); + + if (%timeMS > 30000) + notifyMatchStart(%timeMS); + + if (%timeMS >= 30000) + Game.thirtyCount = schedule(%timeMS - 30000, Game, "notifyMatchStart", 30000); + if (%timeMS >= 15000) + Game.fifteenCount = schedule(%timeMS - 15000, Game, "notifyMatchStart", 15000); + if (%timeMS >= 10000) + Game.tenCount = schedule(%timeMS - 10000, Game, "notifyMatchStart", 10000); + if (%timeMS >= 5000) + Game.fiveCount = schedule(%timeMS - 5000, Game, "notifyMatchStart", 5000); + if (%timeMS >= 4000) + Game.fourCount = schedule(%timeMS - 4000, Game, "notifyMatchStart", 4000); + if (%timeMS >= 3000) + Game.threeCount = schedule(%timeMS - 3000, Game, "notifyMatchStart", 3000); + if (%timeMS >= 2000) + Game.twoCount = schedule(%timeMS - 2000, Game, "notifyMatchStart", 2000); + if (%timeMS >= 1000) + Game.oneCount = schedule(%timeMS - 1000, Game, "notifyMatchStart", 1000); +} + +function EndCountdown(%timeMS) +{ + echo("mission end countdown..."); + + if (isObject(Game)) + %game = Game.getId(); + else + return; + + if (%timeMS >= 60000) + Game.endsixtyCount = schedule(%timeMS - 60000, Game, "notifyMatchEnd", 60000); + if (%timeMS >= 30000) + Game.endthirtyCount = schedule(%timeMS - 30000, Game, "notifyMatchEnd", 30000); + if (%timeMS >= 10000) + Game.endtenCount = schedule(%timeMS - 10000, Game, "notifyMatchEnd", 10000); + if (%timeMS >= 5000) + Game.endfiveCount = schedule(%timeMS - 5000, Game, "notifyMatchEnd", 5000); + if (%timeMS >= 4000) + Game.endfourCount = schedule(%timeMS - 4000, Game, "notifyMatchEnd", 4000); + if (%timeMS >= 3000) + Game.endthreeCount = schedule(%timeMS - 3000, Game, "notifyMatchEnd", 3000); + if (%timeMS >= 2000) + Game.endtwoCount = schedule(%timeMS - 2000, Game, "notifyMatchEnd", 2000); + if (%timeMS >= 1000) + Game.endoneCount = schedule(%timeMS - 1000, Game, "notifyMatchEnd", 1000); +} + +function CancelCountdown() +{ + if (Game.sixtyCount !$= "") + cancel(Game.sixtyCount); + if (Game.thirtyCount !$= "") + cancel(Game.thirtyCount); + if (Game.fifteenCount !$= "") + cancel(Game.fifteenCount); + if (Game.tenCount !$= "") + cancel(Game.tenCount); + if (Game.fiveCount !$= "") + cancel(Game.fiveCount); + if (Game.fourCount !$= "") + cancel(Game.fourCount); + if (Game.threeCount !$= "") + cancel(Game.threeCount); + if (Game.twoCount !$= "") + cancel(Game.twoCount); + if (Game.oneCount !$= "") + cancel(Game.oneCount); + if (isObject(Game)) + cancel(Game.matchStart); + + Game.matchStart = ""; + Game.thirtyCount = ""; + Game.fifteenCount = ""; + Game.tenCount = ""; + Game.fiveCount = ""; + Game.fourCount = ""; + Game.threeCount = ""; + Game.twoCount = ""; + Game.oneCount = ""; + + $countdownStarted = false; +} + +function CancelEndCountdown() +{ + //cancel the mission end countdown... + if (Game.endsixtyCount !$= "") + cancel(Game.endsixtyCount); + if (Game.endthirtyCount !$= "") + cancel(Game.endthirtyCount); + if (Game.endtenCount !$= "") + cancel(Game.endtenCount); + if (Game.endfiveCount !$= "") + cancel(Game.endfiveCount); + if (Game.endfourCount !$= "") + cancel(Game.endfourCount); + if (Game.endthreeCount !$= "") + cancel(Game.endthreeCount); + if (Game.endtwoCount !$= "") + cancel(Game.endtwoCount); + if (Game.endoneCount !$= "") + cancel(Game.endoneCount); + + Game.endmatchStart = ""; + Game.endthirtyCount = ""; + Game.endtenCount = ""; + Game.endfiveCount = ""; + Game.endfourCount = ""; + Game.endthreeCount = ""; + Game.endtwoCount = ""; + Game.endoneCount = ""; +} + +function resetServerDefaults() +{ + $resettingServer = true; + echo( "Resetting server defaults..." ); + + if ( isObject( Game ) ) + Game.gameOver(); + + // Override server defaults with prefs: + exec( "scripts/ServerDefaults.cs" ); + exec( $serverprefs ); + + if ( !isDemo() ) + { + //convert the team skin and name vars to tags... + %index = 0; + while ($Host::TeamSkin[%index] !$= "") + { + $TeamSkin[%index] = addTaggedString($Host::TeamSkin[%index]); + %index++; + } + + %index = 0; + while ($Host::TeamName[%index] !$= "") + { + $TeamName[%index] = addTaggedString($Host::TeamName[%index]); + %index++; + } + + // Get the hologram names from the prefs... + %index = 1; + while ( $Host::holoName[%index] !$= "" ) + { + $holoName[%index] = $Host::holoName[%index]; + %index++; + } + } + + // kick all bots... + removeAllBots(); + + // add bots back if they were there before.. + if ( !isDemo() && $Host::botsEnabled ) + initGameBots( $Host::Map, $Host::MissionType ); + + // load the missions + loadMission( $Host::Map, $Host::MissionType ); + $resettingServer = false; + echo( "Server reset complete." ); +} + +function removeAllBots() +{ + while( ClientGroup.getCount() ) + { + %client = ClientGroup.getObject(0); + if (%client.isAIControlled()) + %client.drop(); + else + %client.delete(); + } +} + +//------------------------------------------------------------------------------ +function getServerGUIDList() +{ + %count = ClientGroup.getCount(); + for ( %i = 0; %i < %count; %i++ ) + { + %cl = ClientGroup.getObject( %i ); + if ( isObject( %cl ) && !%cl.isSmurf && !%cl.isAIControlled() ) + { + %guid = getField( %cl.getAuthInfo(), 3 ); + if ( %guid != 0 ) + { + if ( %list $= "" ) + %list = %guid; + else + %list = %list TAB %guid; + } + } + } + + return( %list ); +} + +//------------------------------------------------------------------------------ +// will return the first admin found on the server +function getAdmin() +{ + %admin = 0; + for ( %clientIndex = 0; %clientIndex < ClientGroup.getCount(); %clientIndex++ ) + { + %cl = ClientGroup.getObject( %clientIndex ); + if (%cl.isAdmin || %cl.isSuperAdmin) + { + %admin = %cl; + break; + } + } + return %admin; +} + +function serverCmdSetPDAPose(%client, %val) +{ + if (!isObject(%client.player)) + return; + + // if client is in a vehicle, return + if (%client.player.isMounted()) + return; + + if (%val) + { + // play "PDA" animation thread on player + %client.player.setActionThread("PDA", false); + } + else + { + // cancel PDA animation thread + %client.player.setActionThread("root", true); + } +} + +function serverCmdProcessGameLink(%client, %arg1, %arg2, %arg3, %arg4, %arg5) +{ + Game.processGameLink(%client, %arg1, %arg2, %arg3, %arg4, %arg5); +} + +function reLightAllClients() { + %count = ClientGroup.getCount(); + for(%i = 0; %i < %count; %i++) { + %client = ClientGroup.getObject(%i); + if (%client.currentPhase == 4) + commandToClient(%client,'reLightMission'); + } +} + +function killerFog() { + cancel($KillerFogSched); + if (!isObject(MissionArea)) { + error("killerFog: no MissionArea!"); + return; + } + if (MissionArea.killerFogAlt $= "") { + error("killerFog: no kill altitude!"); + return; + } + %alt = MissionArea.killerFogAlt; + %count = ClientGroup.getCount(); + for(%i = 0; %i < %count; %i++) { + %cl = ClientGroup.getObject(%i); + %pl = %cl.player; + if (isObject(%pl)) { + if (%pl.getState() !$= "Dead" && %cl.isJailed != true) { + %pos = %pl.getPosition(); + if (getWord(%pos,2) < %alt) { + %vehicle = %pl.getObjectMount(); + if (%pl.isMounted()) { + if (%pl.vehicleTurret) + %pl.vehicleTurret.getDataBlock().playerDismount(%pl.vehicleTurret); + else { + %pl.getDataBlock().doDismount(%pl,true); + %pl.mountVehicle = false; + } + } + if (getWord(%pos,2) > -11000) + %pl.setPosition(getWords(%pos,0,1) SPC -12000); + %pl.scriptKill($DamageType::KillerFog); + if (isObject(%vehicle)) { + if ((%vehicle.getType() & $TypeMasks::VehicleObjectType) && (!%vehicle.fogKilled)) { + %vehicle.fogKilled = true; + %vehicle.schedule(10,setPosition,getWords(%vehicle.getPosition(),0,1) SPC -12000); + %vehicle.schedule(3000,setDamageState,Destroyed); + } + } + } + } + } + } + $KillerFogSched = schedule(500,0,killerFog); +} + +function serverCmdConstructionRegisterClient(%client,%version) { + %client.constructionClient = true; + %client.constructionClientVersion = %version; + echo(%client SPC getTaggedString(%client.name) @ " registered as Construction Mod Client, version " @ %version @ "."); +} + +function serverCmdConstructionQueryServer(%client) { + commandToClient(%client,'QueryServerReply',"Construction Mod Server",$ModVersion,$ModCredits,"2"); +} + +function limitVelocityLoop() { + cancel($limitVelocityLoop); + %count = ClientGroup.getCount(); + for (%i=0;%i<%count;%i++) { + %client = ClientGroup.getObject(%i); + %plyr = %client.player; + if (isObject(%plyr)) { +// %vehicle = %plyr.getObjectMount(); +// if (%vehicle) +// limitObjectVelocity(%vehicle); + limitObjectVelocity(%plyr); + } + } + %count = getWordCount($VehicleList); + for(%i=0;%i<%count;%i++) { + %obj= getWord($VehicleList,%i); + if (isObject(%obj)) { + if ((%obj.getType() & $TypeMasks::VehicleObjectType)) { + limitObjectVelocity(%obj); + } + } + } + $limitVelocityLoop = schedule(1000,0,"limitVelocityLoop"); +} + +function limitObjectVelocity(%obj) { + %vec = %obj.getVelocity(); + %vel = vectorLen(%vec); + if (%vel > 1400) { + %obj.setVelocity(vectorScale(vectorNormalize(%vec),1400)); + if (%obj.getType() & $TypeMasks::VehicleObjectType) { + %obj.setFrozenState(true); + %obj.schedule(500,setDamageState,Destroyed); + } + } + // doing this here, since we already have the loop set up :P + if (!$Host::AllowUnderground) { + if (%obj.getType() & $TypeMasks::PlayerObjectType) { + if (%obj.client.isJailed || %obj.getState() $= "Dead" || %obj.getObjectMount()) + return; + } + if (%obj.fogKilled) + return; + %pos = %obj.getPosition(); + %terrain = getWord(getTerrainHeight2(%pos),2); + if (getWord(%pos,2) < %terrain) { + %obj.setPosition(getWords(%pos,0,1) SPC %terrain + (getWord(%pos,2) - getWord(%obj.getWorldBox(),2)) + 0.1); + } + } +} diff --git a/scripts/serverCommanderMap.cs b/scripts/serverCommanderMap.cs new file mode 100644 index 0000000..d5b8098 --- /dev/null +++ b/scripts/serverCommanderMap.cs @@ -0,0 +1,373 @@ +//------------------------------------------------------------------------------ +// Object control +//------------------------------------------------------------------------------ +function getControlObjectType(%obj,%user) +{ + // turrets (camera is a turret) + if (%obj.getType() & $TypeMasks::TurretObjectType) + { + %barrel = %obj.getMountedImage(0); + if (isObject(%barrel)) + return(addTaggedString(%barrel.getName())); + } + + // unknown + return('Unknown'); +} + +function serverCmdControlObject(%client, %targetId) +{ + // match started: + if (!$MatchStarted) + { + commandToClient(%client, 'ControlObjectResponse', false, "mission has not started."); + return; + } + + // object: + %obj = getTargetObject(%targetId); + if (%obj == -1) + { + commandToClient(%client, 'ControlObjectResponse', false, "failed to find target object."); + return; + } + + // shapebase: + if (!(%obj.getType() & $TypeMasks::ShapeBaseObjectType)) + { + commandToClient(%client, 'ControlObjectResponse', false, "object cannot be controlled."); + return; + } + + // can control: + if (!%obj.getDataBlock().canControl) + { + commandToClient(%client, 'ControlObjectResponse', false, "object cannot be controlled."); + return; + } + + // check damage: + if (%obj.getDamageState() !$= "Enabled") + { + commandToClient(%client, 'ControlObjectResponse', false, "object is " @ %obj.getDamageState()); + return; + } + + // powered: + if (!%obj.isPowered()) + { + commandToClient(%client, 'ControlObjectResponse', false, "object is not powered."); + return; + } + + // controlled already: + %control = %obj.getControllingClient(); + if (%control) + { + if (%control == %client) + commandToClient(%client, 'ControlObjectResponse', false, "you are already controlling that object."); + else + commandToClient(%client, 'ControlObjectResponse', false, "someone is already controlling that object."); + return; + } + + // same team? + if (getTargetSensorGroup(%targetId) != %client.getSensorGroup()) + { + commandToClient(%client, 'ControlObjectResonse', false, "cannot control enemy objects."); + return; + } + + // dead? + if (%client.player == 0 && getTargetDataBlock(%targetId).getName() !$= "TurretPrisonCamera") { + commandToClient(%client, 'ControlObjectResponse', false, "dead people cannot control objects."); + return; + } + + if (%client.isJailed) { + return; + } + + // turret in purebuild mode? + if ((%obj.getType() & $TypeMasks::TurretObjectType) + && $Host::Purebuild == 1 + && !(%client.isAdmin || %client.isSuperAdmin) + && %obj.getDataBlock().getName() !$= "TurretDeployedCamera" + && %obj.getDataBlock().getName() !$= "TurretPrisonCamera") { + commandToClient(%client, 'ControlObjectResponse', false, "cannot control turrets in purebuild mode."); + return; + } + +//[[CHANGE]]Make sure you can command a bomber... and ride it the same time ;) + + //mounted in a vehicle? + //if (%client.player.isMounted()) + //{ + // commandToClient(%client, 'ControlObjectResponse', false, "can't control objects while mounted in a vehicle."); + // return; + //} + + %client.setControlObject(%obj); + commandToClient(%client, 'ControlObjectResponse', true, getControlObjectType(%obj,%client.player)); + %objName = getTaggedString(getTargetName(%obj.target)) SPC getTaggedString(getTargetType(%obj.target)); + if (%obj $= "") + %objName = %obj.getDataBlock().getName(); + if ($Host::Purebuild == 1) + messageAll('msgClient','\c2%1 is now controlling %2.',%client.name,%objName); + else + messageTeam(%client.team,'msgClient','\c2%1 is now controlling %2.',%client.name,%objName); + +//[[CHANGE]] Make sure the controlled object knows how is controlling it. + %obj.clientControl = %client; + +///[[CHANGE]] Includes the remote station functionality. + + if (%obj.getType() & $TypeMasks::StationObjectType) + { +//Lost of commented stuff... should not be nessesary. + %colObj = %client.player; + //%colObj.inStation = true; + + //commandToClient(%colObj.client,'setStationKeys', true); + messageClient(%colObj.client, 'CloseHud', "", 'inventoryScreen'); + //commandToClient(%colObj.client, 'TogglePlayHuds', true); + %obj.triggeredBy = %colObj; + //%obj.getDataBlock().stationTriggered(%obj, 1); + %colObj.station = %obj; + //%colObj.lastWeapon = ( %colObj.getMountedImage($WeaponSlot) == 0 ) ? "" : %colObj.getMountedImage($WeaponSlot).getName().item; + //%colObj.unmountImage($WeaponSlot); + // Make sure none of the other popup huds are active: + //messageClient( %obj.triggeredBy.client, 'CloseHud', "", 'scoreScreen' ); + //messageClient( %obj.triggeredBy.client, 'CloseHud', "", 'inventoryScreen' ); + //Make sure the client doesn't transport.. but does get command. + %client.telebuy = 1; + + + //Stuff from observing + %data = %obj.getDataBlock(); + + %obsData = %data.observeParameters; + %obsX = firstWord(%obsData); + %obsY = getWord(%obsData, 1); + %obsZ = getWord(%obsData, 2); + + // don't set the camera mode so that it does not interfere with spawning + %transform = %obj.getTransform(); + + // create a fresh camera to observe through... (could add to a list on + // the observed camera to be removed when that object dies/...) + + if ( !isObject( %client.comCam ) ) + { + %client.comCam = new Camera() + { + dataBlock = CommanderCamera; + }; + MissionCleanup.add(%client.comCam); + } + + %client.comCam.setTransform(%transform); + %client.comCam.setOrbitMode(%obj, %transform, %obsX, %obsY, %obsZ); + + %client.setControlObject(%client.comCam); + commandToClient(%client, 'CameraAttachResponse', true); + + //Display the Vehicle Station GUI + //%client.player.AttachBeacon(); + //%client.player.schedule(20000,"RemoveBeacon"); + //%client.player.scheduel(1000,RemoveBeacon()); + + commandToClient(%obj.triggeredBy.client, 'StationVehicleShowHud'); + } + if (isObject(%client.player)) { + %client.player.RemoveBeacon(); + %client.player.AttachBeacon(); + } +//[[End CHANGE]] +} + +//[[CHANGE]] Pretty straigh forward functions. +function Player::AttachBeacon(%obj) +{ + %beacon = new BeaconObject(){ + datablock = BomberBeacon; + }; + if (%obj.team == 1) + %team = 2; + else + %team = 1; + %beacon.team = %team; + %beacon.owner = %obj; + %beacon.setTarget(%team); + %obj.mountObject(%beacon, 4); + %obj.enemyBeacon = %beacon; + MissionCleanup.add(%beacon); + %beacon.setBeaconType(enemy); +} +function Player::RemoveBeacon(%obj) +{ +if (%obj.enemybeacon) + %obj.enemyBeacon.delete(); + %obj.enemyBeacon = ""; +} +//[[End CHANGE]] +//------------------------------------------------------------------------------ +// TV Functions +//------------------------------------------------------------------------------ +function resetControlObject(%client) { + if ( isObject( %client.comCam ) ) + %client.comCam.delete(); + if (isObject(%client.player) && !%client.player.isDestroyed() && $MatchStarted) + %client.setControlObject(%client.player); + else + %client.setControlObject(%client.camera); + + // [[CHANGE]] make sure all is reset. + if (isObject(%client.player)) { + %client.player.station.triggeredBy = ""; + %client.player.station = ""; + %client.player.RemoveBeacon(); + } +} + +function serverCmdResetControlObject(%client) { + resetControlObject(%client); + commandToClient(%client, 'ControlObjectReset'); + // -------------------------------------------------------- + // z0dd - ZOD 4/18/02. Vehicle reticle disappearance fix. + // commandToClient(%client, 'RemoveReticle'); + //if(isObject(%client.player)) + //{ + // %weapon = %client.player.getMountedImage($WeaponSlot); + // %client.setWeaponsHudActive(%weapon.item); + //} + if(isObject(%client.player)) + { + if(%client.player.isPilot() || %client.player.isWeaponOperator()) + { + return; + } + else + { + commandToClient(%client, 'RemoveReticle'); + %weapon = %client.player.getMountedImage($WeaponSlot); + %client.setWeaponsHudActive(%weapon.item); + } + } + // End z0dd - ZOD + // -------------------------------------------------------- + + // [[CHANGE]] make sure all is reset. + if (isObject(%client.player)) { + %client.player.station.triggeredBy = ""; + %client.player.station = ""; + %client.player.RemoveBeacon(); + } +} + +function serverCmdAttachCommanderCamera(%client, %target) +{ + // dont allow observing until match has started + if (!$MatchStarted) + { + commandToClient(%client, 'CameraAttachResponse', false); + return; + } + + %obj = getTargetObject(%target); + if ((%obj == -1) || (%target == -1)) + { + commandToClient(%client, 'CameraAttachResponse', false); + return; + } + + // shape base object? + if (!(%obj.getType() & $TypeMasks::ShapeBaseObjectType)) + { + commandToClient(%client, 'CameraAttachResponse', false); + return; + } + + // can be observed? + if (!%obj.getDataBlock() || !%obj.getDataBlock().canObserve) + { + commandToClient(%client, 'CameraAttachResponse', false); + return; + } + + // same team? + if (getTargetSensorGroup(%target) != %client.getSensorGroup()) + { + commandToClient(%client, 'CameraAttachResponse', false); + return; + } + + // powered? + if (!%obj.isPowered()) + { + commandToClient(%client, 'CameraAttachResponse', false); + return; + } + + // client connection? + if (%obj.getClassName() $= "GameConnection") + { + %player = %obj.player; + if (%obj == %client) + { + if (isObject(%player) && !%player.isDestroyed()) + { + + %client.setControlObject(%player); + commandToClient(%client, 'CameraAttachResponse', true); + return; + } + } + + %obj = %player; + } + + if (!isObject(%obj) || %obj.isDestroyed()) + { + commandToClient(%client, 'CameraAttachResponse', false); + return; + } + + %data = %obj.getDataBlock(); + + %obsData = %data.observeParameters; + %obsX = firstWord(%obsData); + %obsY = getWord(%obsData, 1); + %obsZ = getWord(%obsData, 2); + + // don't set the camera mode so that it does not interfere with spawning + %transform = %obj.getTransform(); + + // create a fresh camera to observe through... (could add to a list on + // the observed camera to be removed when that object dies/...) + if ( !isObject( %client.comCam ) ) + { + %client.comCam = new Camera() + { + dataBlock = CommanderCamera; + }; + MissionCleanup.add(%client.comCam); + } + + %client.comCam.setTransform(%transform); + %client.comCam.setOrbitMode(%obj, %transform, %obsX, %obsY, %obsZ); + + %client.setControlObject(%client.comCam); + commandToClient(%client, 'CameraAttachResponse', true); +} + +//------------------------------------------------------------------------------ +// Scoping +function serverCmdScopeCommanderMap(%client, %scope) +{ + if (%scope) + resetControlObject(%client); + %client.scopeCommanderMap(%scope); + + commandToClient(%client, 'ScopeCommanderMap', %scope); +} \ No newline at end of file diff --git a/scripts/skywrite.cs b/scripts/skywrite.cs new file mode 100644 index 0000000..0bcaa12 --- /dev/null +++ b/scripts/skywrite.cs @@ -0,0 +1,606 @@ +//A nice collection of characters. +// + +//Normal +//"a b c d e f g h i j k l m n o p q r s t u v w x y z" + +//a +$SW::Info["a"] = "5 0.85"; //Pieces,Space +$SW::Sizes["a",0] = "0.3 0.50 0.55 0.50 0.3 0.60"; +$SW::Sizes["a",1] = "0.55 0.2 0.65 0.2 0.55 0.55"; +$SW::Sizes["a",2] = "0.3 0.1 0.75 0.1 0.3 0.2"; +$SW::Sizes["a",3] = "0.2 0.15 0.3 0.15 0.2 0.35"; +$SW::Sizes["a",4] = "0.3 0.3 0.55 0.3 0.3 0.4"; + +//b +$SW::Info["b"] = "4 0.7"; //Pieces,Space +$SW::Sizes["b",0] = "0.2 0.1 0.3 0.1 0.2 0.8"; +$SW::Sizes["b",1] = "0.3 0.40 0.60 0.40 0.3 0.50"; +$SW::Sizes["b",2] = "0.3 0.10 0.60 0.10 0.3 0.20"; +$SW::Sizes["b",3] = "0.60 0.15 0.70 0.15 0.60 0.45"; + +//c +$SW::Info["c"] = "3 0.75"; //Pieces,Space +$SW::Sizes["c",0] = "0.2 0.15 0.3 0.15 0.2 0.50"; +$SW::Sizes["c",1] = "0.3 0.45 0.65 0.45 0.3 0.55"; +$SW::Sizes["c",2] = "0.3 0.10 0.65 0.10 0.3 0.20"; + +//d +$SW::Info["d"] = "4 0.8"; //Pieces,Space +$SW::Sizes["d",0] = "0.2 0.15 0.3 0.15 0.2 0.45"; +$SW::Sizes["d",1] = "0.3 0.40 0.60 0.40 0.3 0.50"; +$SW::Sizes["d",2] = "0.3 0.10 0.60 0.10 0.3 0.20"; +$SW::Sizes["d",3] = "0.60 0.1 0.70 0.1 0.60 0.8"; + +//e +$SW::Info["e"] = "5 0.75"; //Pieces,Space +$SW::Sizes["e",0] = "0.2 0.15 0.3 0.15 0.2 0.50"; +$SW::Sizes["e",1] = "0.3 0.45 0.55 0.45 0.3 0.55"; +$SW::Sizes["e",2] = "0.3 0.10 0.65 0.10 0.3 0.20"; +$SW::Sizes["e",3] = "0.55 0.35 0.65 0.35 0.55 0.50"; +$SW::Sizes["e",4] = "0.3 0.25 0.65 0.25 0.3 0.35"; + +//f +$SW::Info["f"] = "3 0.8"; //Pieces,Space +$SW::Sizes["f",0] = "0.30 0.5 0.70 0.5 0.30 0.60"; +$SW::Sizes["f",1] = "0.45 0.1 0.55 0.1 0.45 0.7"; +$SW::Sizes["f",2] = "0.50 0.65 0.70 0.65 0.50 0.75"; + +//g +$SW::Info["g"] = "5 0.75"; //Pieces,Space +$SW::Sizes["g",0] = "0.3 0.50 0.55 0.50 0.3 0.60"; +$SW::Sizes["g",1] = "0.55 0.05 0.65 0.05 0.55 0.60"; +$SW::Sizes["g",2] = "0.3 0.0 0.60 0.0 0.3 0.1"; +$SW::Sizes["g",3] = "0.25 0.30 0.35 0.30 0.25 0.55"; +$SW::Sizes["g",4] = "0.3 0.25 0.55 0.25 0.3 0.35"; + +//h +$SW::Info["h"] = "3 0.7"; //Pieces,Space +$SW::Sizes["h",0] = "0.2 0.1 0.3 0.1 0.2 0.8"; +$SW::Sizes["h",1] = "0.3 0.40 0.60 0.40 0.3 0.50"; +$SW::Sizes["h",2] = "0.55 0.1 0.65 0.1 0.55 0.45"; + +//i +$SW::Info["i"] = "2 0.35"; //Pieces,Space +$SW::Sizes["i",0] = "0.15 0.1 0.25 0.1 0.15 0.5"; +$SW::Sizes["i",1] = "0.15 0.6 0.25 0.6 0.15 0.7"; + +//j +$SW::Info["j"] = "3 0.45"; //Pieces,Space +$SW::Sizes["j",0] = "0.25 0.05 0.35 0.05 0.25 0.6"; +$SW::Sizes["j",1] = "0.25 0.7 0.35 0.7 0.25 0.8"; +$SW::Sizes["j",2] = "0.10 0.0 0.30 0.0 0.10 0.1"; + +//k +$SW::Info["k"] = "3 0.6"; //Pieces,Space +$SW::Sizes["k",0] = "0.2 0.1 0.3 0.1 0.2 0.7"; +$SW::Sizes["k",1] = "0.3 0.25 0.50 0.45 0.23 0.32"; +$SW::Sizes["k",2] = "0.3 0.25 0.45 0.1 0.37 0.32"; + +//l +$SW::Info["l"] = "1 0.4"; //Pieces,Space +$SW::Sizes["l",0] = "0.2 0.1 0.3 0.1 0.2 0.8"; + +//m +$SW::Info["m"] = "5 0.9"; //Pieces,Space +$SW::Sizes["m",0] = "0.2 0.1 0.3 0.1 0.2 0.55"; +$SW::Sizes["m",1] = "0.3 0.40 0.50 0.40 0.3 0.50"; +$SW::Sizes["m",2] = "0.45 0.1 0.55 0.1 0.45 0.45"; +$SW::Sizes["m",3] = "0.55 0.40 0.75 0.40 0.55 0.50"; +$SW::Sizes["m",4] = "0.70 0.1 0.80 0.1 0.70 0.45"; + +//n +$SW::Info["n"] = "3 0.65"; //Pieces,Space +$SW::Sizes["n",0] = "0.2 0.1 0.3 0.1 0.2 0.55"; +$SW::Sizes["n",1] = "0.3 0.40 0.50 0.40 0.3 0.50"; +$SW::Sizes["n",2] = "0.45 0.1 0.55 0.1 0.45 0.45"; + +//o +$SW::Info["o"] = "4 0.65"; //Pieces,Space +$SW::Sizes["o",0] = "0.2 0.15 0.3 0.15 0.2 0.45"; +$SW::Sizes["o",1] = "0.25 0.40 0.50 0.40 0.3 0.50"; +$SW::Sizes["o",2] = "0.45 0.15 0.55 0.15 0.45 0.45"; +$SW::Sizes["o",3] = "0.25 0.1 0.50 0.1 0.25 0.2"; + +//p +$SW::Info["p"] = "4 0.8"; //Pieces,Space +$SW::Sizes["p",0] = "0.3 0.50 0.55 0.50 0.3 0.60"; +$SW::Sizes["p",1] = "0.5 0.30 0.6 0.30 0.5 0.55"; +$SW::Sizes["p",2] = "0.2 0.0 0.3 0.00 0.2 0.60"; +$SW::Sizes["p",3] = "0.3 0.25 0.55 0.25 0.3 0.35"; + +//q +$SW::Info["q"] = "4 0.75"; //Pieces,Space +$SW::Sizes["q",0] = "0.3 0.50 0.55 0.50 0.3 0.60"; +$SW::Sizes["q",1] = "0.55 0.0 0.65 0.0 0.55 0.60"; +$SW::Sizes["q",2] = "0.25 0.30 0.35 0.30 0.25 0.55"; +$SW::Sizes["q",3] = "0.3 0.25 0.55 0.25 0.3 0.35"; + +//r +$SW::Info["r"] = "4 0.6"; //Pieces,Space +$SW::Sizes["r",0] = "0.2 0.1 0.3 0.1 0.2 0.55"; +$SW::Sizes["r",1] = "0.3 0.38 0.35 0.38 0.3 0.48"; +$SW::Sizes["r",2] = "0.3 0.40 0.50 0.40 0.3 0.50"; +$SW::Sizes["r",3] = "0.45 0.38 0.50 0.38 0.45 0.48"; + +//s +$SW::Info["s"] = "7 0.6"; //Pieces,Space +$SW::Sizes["s",0] = "0.2 0.40 0.3 0.40 0.2 0.50"; +$SW::Sizes["s",1] = "0.25 0.45 0.45 0.45 0.3 0.55"; +$SW::Sizes["s",2] = "0.2 0.40 0.40 0.2 0.25 0.50"; +$SW::Sizes["s",3] = "0.40 0.15 0.5 0.15 0.4 0.25"; +$SW::Sizes["s",4] = "0.25 0.1 0.45 0.1 0.2 0.2"; +$SW::Sizes["s",5] = "0.40 0.40 0.5 0.40 0.4 0.5"; +$SW::Sizes["s",6] = "0.2 0.15 0.3 0.15 0.2 0.25"; + +//t +$SW::Info["t"] = "3 0.75"; //Pieces,Space +$SW::Sizes["t",0] = "0.35 0.5 0.65 0.5 0.35 0.60"; +$SW::Sizes["t",1] = "0.45 0.1 0.55 0.1 0.45 0.7"; +$SW::Sizes["t",2] = "0.55 0.1 0.65 0.1 0.55 0.2"; + +//u +$SW::Info["u"] = "3 0.60"; //Pieces,Space +$SW::Sizes["u",0] = "0.2 0.1 0.3 0.1 0.2 0.50"; +$SW::Sizes["u",1] = "0.25 0.05 0.50 0.05 0.3 0.15"; +$SW::Sizes["u",2] = "0.45 0.1 0.55 0.1 0.45 0.50"; + +//v +$SW::Info["v"] = "2 0.60"; //Pieces,Space +$SW::Sizes["v",0] = "0.1 0.5 0.3 0.1 0.15 0.55"; +$SW::Sizes["v",1] = "0.3 0.1 0.5 0.5 0.25 0.15"; + +//w +$SW::Info["w"] = "4 0.9"; //Pieces,Space +$SW::Sizes["w",0] = "0.1 0.5 0.3 0.1 0.15 0.55"; +$SW::Sizes["w",1] = "0.3 0.1 0.5 0.5 0.25 0.15"; +$SW::Sizes["w",2] = "0.4 0.5 0.6 0.1 0.45 0.55"; +$SW::Sizes["w",3] = "0.6 0.1 0.8 0.5 0.55 0.15"; + +//x +$SW::Info["x"] = "2 0.5"; //Pieces,Space +$SW::Sizes["x",0] = "0.1 0.4 0.38 0.1 0.15 0.45"; +$SW::Sizes["x",1] = "0.12 0.1 0.4 0.4 0.07 0.15"; + +//y +$SW::Info["y"] = "3 0.60"; //Pieces,Space +$SW::Sizes["y",0] = "0.1 0.5 0.25 0.25 0.15 0.55"; +$SW::Sizes["y",1] = "0.3 0.15 0.5 0.5 0.25 0.2"; +$SW::Sizes["y",2] = "0.15 0.10 0.3 0.1 0.2 0.18"; + +//z +$SW::Info["z"] = "3 0.6"; //Pieces,Space +$SW::Sizes["z",0] = "0.1 0.40 0.4 0.40 0.1 0.50"; +$SW::Sizes["z",1] = "0.15 0.1 0.4 0.4 0.1 0.15"; +$SW::Sizes["z",2] = "0.1 0.1 0.4 0.1 0.1 0.2"; + +//Numbers +//"1 2 3 4 5 6 7 8 9 0" + +//1 +$SW::Info["1"] = "3 0.65"; //Pieces,Space +$SW::Sizes["1",0] = "0.3 0.1 0.4 0.1 0.3 0.8"; +$SW::Sizes["1",1] = "0.2 0.6 0.4 0.75 0.17 0.67"; +$SW::Sizes["1",2] = "0.15 0.0 0.55 0.0 0.1 0.1"; + +//2 +$SW::Info["2"] = "4 0.65"; //Pieces,Space +$SW::Sizes["2",0] = "0.1 0.7 0.5 0.7 0.1 0.8"; +$SW::Sizes["2",1] = "0.45 0.5 0.55 0.5 0.45 0.75"; +$SW::Sizes["2",2] = "0.15 0.0 0.55 0.5 0.08 0.07"; +$SW::Sizes["2",3] = "0.07 0.0 0.55 0.0 0.07 0.1"; + +//3 +$SW::Info["3"] = "5 0.65"; //Pieces,Space +$SW::Sizes["3",0] = "0.1 0.7 0.5 0.7 0.1 0.8"; +$SW::Sizes["3",1] = "0.45 0.45 0.55 0.45 0.45 0.75"; +$SW::Sizes["3",2] = "0.1 0.35 0.5 0.35 0.1 0.45"; +$SW::Sizes["3",3] = "0.45 0.05 0.55 0.05 0.45 0.35"; +$SW::Sizes["3",4] = "0.1 0.0 0.5 0.0 0.1 0.1"; + +//4 + +$SW::Info["4"] = "3 0.75"; //Pieces,Space +$SW::Sizes["4",0] = "0.4 0.0 0.5 0.0 0.4 0.8"; +$SW::Sizes["4",1] = "0.1 0.25 0.5 0.75 0.17 0.32"; +$SW::Sizes["4",2] = "0.1 0.25 0.65 0.25 0.1 0.35"; + +//5 +$SW::Info["5"] = "5 0.7"; //Pieces,Space +$SW::Sizes["5",0] = "0.1 0.35 0.2 0.35 0.1 0.8"; +$SW::Sizes["5",1] = "0.2 0.35 0.55 0.35 0.2 0.45"; +$SW::Sizes["5",2] = "0.1 0.0 0.55 0.00 0.1 0.10"; +$SW::Sizes["5",3] = "0.5 0.05 0.60 0.05 0.50 0.40"; +$SW::Sizes["5",4] = "0.2 0.70 0.60 0.70 0.2 0.8"; + +//6 +$SW::Info["6"] = "6 0.7"; //Pieces,Space +$SW::Sizes["6",0] = "0.1 0.05 0.2 0.05 0.1 0.7"; +$SW::Sizes["6",1] = "0.2 0.35 0.55 0.35 0.2 0.45"; +$SW::Sizes["6",2] = "0.15 0.0 0.55 0.00 0.15 0.10"; +$SW::Sizes["6",3] = "0.50 0.05 0.60 0.05 0.50 0.40"; +$SW::Sizes["6",4] = "0.15 0.65 0.60 0.70 0.08 0.72"; + +//7 +$SW::Info["7"] = "2 0.6"; //Pieces,Space +$SW::Sizes["7",0] = "0.1 0.7 0.5 0.7 0.1 0.8"; +$SW::Sizes["7",1] = "0.2 0.0 0.5 0.7 0.13 0.07"; + +//8 +$SW::Info["8"] = "7 0.7"; //Pieces,Space +$SW::Sizes["8",0] = "0.1 0.05 0.2 0.05 0.1 0.43"; +$SW::Sizes["8",1] = "0.1 0.45 0.58 0.35 0.17 0.52"; +$SW::Sizes["8",2] = "0.15 0.00 0.55 0.00 0.15 0.15"; +$SW::Sizes["8",3] = "0.50 0.05 0.60 0.05 0.50 0.45"; +$SW::Sizes["8",4] = "0.15 0.70 0.55 0.70 0.15 0.80"; +$SW::Sizes["8",5] = "0.1 0.45 0.2 0.45 0.1 0.75"; +$SW::Sizes["8",6] = "0.50 0.47 0.60 0.47 0.50 0.75"; + +//9 +$SW::Info["9"] = "6 0.7"; //Pieces,Space +$SW::Sizes["9",0] = "0.1 0.45 0.58 0.35 0.17 0.52"; +$SW::Sizes["9",1] = "0.15 0.00 0.55 0.00 0.15 0.15"; +$SW::Sizes["9",2] = "0.50 0.05 0.60 0.05 0.50 0.45"; +$SW::Sizes["9",3] = "0.15 0.70 0.55 0.70 0.15 0.80"; +$SW::Sizes["9",4] = "0.1 0.45 0.2 0.45 0.1 0.75"; +$SW::Sizes["9",5] = "0.50 0.47 0.60 0.47 0.50 0.75"; + +//0 +$SW::Info["0"] = "4 0.7"; //Pieces,Space +$SW::Sizes["0",0] = "0.1 0.05 0.2 0.05 0.1 0.75"; +$SW::Sizes["0",1] = "0.15 0.00 0.55 0.00 0.15 0.15"; +$SW::Sizes["0",2] = "0.50 0.05 0.60 0.05 0.50 0.75"; +$SW::Sizes["0",3] = "0.15 0.70 0.55 0.70 0.15 0.80"; + +//Tribes2 String Chars +// " ' \ + +//" +$SW::Info["\""] = "2 0.40"; //Pieces,Space +$SW::Sizes["\"",0] = "0.15 0.65 0.20 0.65 0.15 0.8"; +$SW::Sizes["\"",1] = "0.25 0.65 0.30 0.65 0.25 0.8"; + +//' +$SW::Info["\'"] = "1 0.30"; //Pieces,Space +$SW::Sizes["\'",0] = "0.15 0.65 0.20 0.65 0.15 0.8"; + +// \ +$SW::Info["\\"] = "1 0.70"; //Pieces,Space +$SW::Sizes["\\",0] = "0.1 0.75 0.6 0.1 0.15 0.8"; + + +//Skywrite string Chars +//+ / + +$SW::Info["/+"] = "2 0.70"; //Pieces,Space +$SW::Sizes["/+",0] = "0.1 0.35 0.6 0.35 0.1 0.45"; +$SW::Sizes["/+",1] = "0.3 0.1 0.4 0.1 0.3 0.7"; + +// / +$SW::Info["//"] = "1 0.70"; //Pieces,Space +$SW::Sizes["//",0] = "0.1 0.1 0.6 0.8 0.05 0.15"; + + +//Sentance builders +//. , : ; ! ? + +//. +$SW::Info["."] = "1 0.30"; //Pieces,Space +$SW::Sizes[".",0] = "0.1 0.1 0.20 0.1 0.1 0.2"; + +//, +$SW::Info[","] = "2 0.30"; //Pieces,Space +$SW::Sizes[",",0] = "0.1 0.1 0.20 0.1 0.1 0.2"; +$SW::Sizes[",",1] = "0.1 0.0 0.2 0.1 0.05 0.05"; + +//: +$SW::Info[":"] = "2 0.30"; //Pieces,Space +$SW::Sizes[":",0] = "0.1 0.2 0.20 0.2 0.1 0.3"; +$SW::Sizes[":",1] = "0.1 0.5 0.20 0.5 0.1 0.6"; + +//; +$SW::Info[";"] = "3 0.30"; //Pieces,Space +$SW::Sizes[";",0] = "0.1 0.2 0.20 0.2 0.1 0.3"; +$SW::Sizes[";",1] = "0.1 0.1 0.2 0.2 0.05 0.15"; +$SW::Sizes[";",2] = "0.1 0.5 0.20 0.5 0.1 0.6"; + +//! +$SW::Info["!"] = "2 0.35"; //Pieces,Space +$SW::Sizes["!",0] = "0.15 0.2 0.25 0.2 0.15 0.8"; +$SW::Sizes["!",1] = "0.15 0.0 0.25 0.0 0.15 0.1"; + +//? +$SW::Info["?"] = "6 0.65"; //Pieces,Space +$SW::Sizes["?",0] = "0.2 0.7 0.5 0.7 0.2 0.8"; +$SW::Sizes["?",1] = "0.15 0.65 0.25 0.65 0.15 0.75"; +$SW::Sizes["?",2] = "0.45 0.5 0.55 0.5 0.45 0.75"; +$SW::Sizes["?",3] = "0.35 0.25 0.55 0.5 0.27 0.33"; +$SW::Sizes["?",4] = "0.25 0.2 0.35 0.2 0.25 0.3"; +$SW::Sizes["?",5] = "0.25 0.0 0.35 0.0 0.25 0.1"; + + + +//# +$SW::Info["#"] = "4 0.55"; //Pieces,Space +$SW::Sizes["#",0] = "0.15 0.15 0.20 0.15 0.15 0.7"; +$SW::Sizes["#",1] = "0.25 0.15 0.30 0.15 0.25 0.7"; +$SW::Sizes["#",2] = "0.05 0.30 0.40 0.30 0.05 0.35"; +$SW::Sizes["#",3] = "0.05 0.50 0.40 0.50 0.05 0.55"; + +//$ +$SW::Info["$"] = "6 0.7"; //Pieces,Space +$SW::Sizes["$",0] = "0.2 0.65 0.55 0.65 0.2 0.75"; +$SW::Sizes["$",1] = "0.15 0.40 0.25 0.40 0.15 0.7"; +$SW::Sizes["$",2] = "0.2 0.40 0.55 0.30 0.27 0.47"; +$SW::Sizes["$",3] = "0.5 0.10 0.60 0.1 0.50 0.40"; +$SW::Sizes["$",4] = "0.2 0.05 0.55 0.05 0.25 0.15"; +$SW::Sizes["$",5] = "0.325 0.0 0.425 0.0 0.325 0.80"; + +//% +$SW::Info["%"] = "3 0.6"; //Pieces,Space +$SW::Sizes["%",0] = "0.4 0.1 0.5 0.0 0.5 0.2"; +$SW::Sizes["%",1] = "0.1 0.0 0.6 0.8 0.03 0.07"; +$SW::Sizes["%",2] = "0.0 0.75 0.1 0.65 0.1 0.85"; + +//& +$SW::Info["&"] = "6 0.7"; //Pieces,Space +$SW::Sizes["&",0] = "0.5 0.0 0.6 0.5 0.48 0.05"; +$SW::Sizes["&",1] = "0.1 0.0 0.5 0.0 0.1 0.1"; +$SW::Sizes["&",2] = "0.05 0.05 0.15 0.05 0.05 0.25"; +$SW::Sizes["&",3] = "0.1 0.20 0.55 0.65 0.05 0.25"; +$SW::Sizes["&",4] = "0.45 0.75 0.55 0.65 0.50 0.80"; +$SW::Sizes["&",5] = "0.25 0.55 0.60 0.60 0.20 0.70"; + + +//Hooks +//( ) [ ] { } < > + +//( +$SW::Info["("] = "3 0.45"; //Pieces,Space +$SW::Sizes["(",0] = "0.155 0.45 0.4 0.75 0.105 0.50"; +$SW::Sizes["(",1] = "0.1 0.3 0.2 0.3 0.1 0.5"; +$SW::Sizes["(",2] = "0.1 0.3 0.35 0.0 0.15 0.35"; + +//) +$SW::Info[")"] = "3 0.4"; //Pieces,Space +$SW::Sizes[")",0] = "0.0 0.75 0.24 0.46 0.05 0.8"; +$SW::Sizes[")",1] = "0.2 0.3 0.3 0.3 0.2 0.5"; +$SW::Sizes[")",2] = "0.05 0.0 0.3 0.3 0.0 0.05"; + +//[ +$SW::Info["["] = "3 0.4"; //Pieces,Space +$SW::Sizes["[",0] = "0.0 0.7 0.3 0.7 0.0 0.8"; +$SW::Sizes["[",1] = "0.0 0.1 0.1 0.1 0.0 0.7"; +$SW::Sizes["[",2] = "0.0 0.0 0.3 0.0 0.0 0.1"; + +//] +$SW::Info["]"] = "3 0.4"; //Pieces,Space +$SW::Sizes["]",0] = "0.0 0.7 0.3 0.7 0.0 0.8"; +$SW::Sizes["]",1] = "0.2 0.1 0.3 0.1 0.2 0.7"; +$SW::Sizes["]",2] = "0.0 0.0 0.3 0.0 0.0 0.1"; + +//{ +$SW::Info["{"] = "4 0.4"; //Pieces,Space +$SW::Sizes["{",0] = "0.15 0.7 0.4 0.7 0.15 0.8"; +$SW::Sizes["{",1] = "0.1 0.1 0.2 0.1 0.1 0.7"; +$SW::Sizes["{",2] = "0.15 0.0 0.4 0.0 0.15 0.1"; +$SW::Sizes["{",3] = "0.0 0.35 0.1 0.35 0.0 0.45"; + +//} +$SW::Info["}"] = "4 0.4"; //Pieces,Space +$SW::Sizes["}",0] = "0.0 0.7 0.25 0.7 0.0 0.8"; +$SW::Sizes["}",1] = "0.2 0.1 0.3 0.1 0.2 0.7"; +$SW::Sizes["}",2] = "0.0 0.0 0.25 0.0 0.0 0.1"; +$SW::Sizes["}",3] = "0.3 0.35 0.4 0.35 0.3 0.45"; + +//< +$SW::Info["<"] = "2 0.45"; //Pieces,Space +$SW::Sizes["<",0] = "0.155 0.35 0.4 0.65 0.105 0.40"; +$SW::Sizes["<",1] = "0.1 0.4 0.35 0.1 0.15 0.45"; + +//> +$SW::Info[">"] = "2 0.6"; //Pieces,Space +$SW::Sizes[">",0] = "0.0 0.65 0.24 0.36 0.05 0.7"; +$SW::Sizes[">",1] = "0.05 0.1 0.3 0.4 0.0 0.15"; + + +//Lines +// = _ - | + +//= +$SW::Info["="] = "2 0.45"; //Pieces,Space +$SW::Sizes["=",0] = "0.05 0.25 0.40 0.25 0.05 0.35"; +$SW::Sizes["=",1] = "0.05 0.50 0.40 0.50 0.05 0.60"; + +//- +$SW::Info["-"] = "1 0.45"; //Pieces,Space +$SW::Sizes["-",0] = "0.05 0.35 0.40 0.35 0.05 0.45"; + +//_ +$SW::Info["_"] = "1 0.45"; //Pieces,Space +$SW::Sizes["_",0] = "0.05 0.05 0.40 0.05 0.05 0.15"; + +//| +$SW::Info["|"] = "1 0.40"; //Pieces,Space +$SW::Sizes["|",0] = "0.15 0.0 0.25 0.0 0.15 0.8"; + + +//Space +$SW::Info["sp"] = "0 0.5"; //Pieces,Space + + +//Capital Letters + +//T +$SW::Info["+t"] = "2 1"; //Pieces,Space +$SW::Sizes["+t",0] = "0 0.8 1 0.8 0 1"; +$SW::Sizes["+t",1] = "0.4 0 0.6 0 0.4 0.8"; + +$SW::Thickness = 0.1; + +function GameConnection::skyWrite(%cl,%word,%dist,%scale,%center,%upright,%angle,%mirror) { + if (%word $= "") + return; + if (%dist $= "" || %dist == 0) + %dist = 50; + if (%scale $= "" || %scale == 0) + %scale = 5; + %word = SW_goodWord(%word); + %obj = %cl.player; + %pos = %obj.getEyepoint(); + %dir = %obj.getEyeVector(); + %location = vectorAdd(%pos,vectorScale(%dir,%dist)); + if (%upright) + %dir = vectorNormalize(getWords(%dir,0,1)); + if (%mirror) + %dir = vectorScale(%dir,-1); + SW_word(%word,%location,%dir,%scale,%center,%cl,%angle); +} + +function SW_word(%word,%pos,%nrm,%scale,%center,%cl,%angle) { + %cl.lastword++; + %z = vectorNormalize(%nrm); + %tx = vectorCross(%nrm,"0 0 1"); + %up = vectorAdd(vectorScale("0 0 1",mCos(mDegToRad(%angle))),vectorScale(%tx,mSin(mDegToRad(%angle)))); + %x = vectorCross(%nrm,%up); + + if (%center) { + for (%td = 0; %td < getWordCount(%word);%td++) { + %letter = getWord(%word,%td); + %space = %space + getWord($SW::Info[%letter],1) * %scale; + } + %space = %space * -0.5; + %pos = vectorAdd(%pos,vectorScale(%up,-0.5 * %scale)); + } + + for (%td = 0; %td < getWordCount(%word);%td++) { + %letter = getWord(%word,%td); + SW_letter(%letter,vectorAdd(%pos,vectorScale(%x,%space)),%nrm,%scale,%cl,%angle); + %space = %space + getWord($SW::Info[%letter],1) * %scale; + } +} + +function SW_letter(%letter,%pos,%nrm,%scale,%cl,%angle) { + %z = vectorNormalize(%nrm); + %tx = vectorCross(%nrm,"0 0 1"); + %up = vectorAdd(vectorScale("0 0 1",mCos(mDegToRad(%angle))),vectorScale(%tx,mSin(mDegToRad(%angle)))); + %x = vectorCross(%nrm,%up); + %y = vectorCross(%x,%nrm); + + %matrix = %x SPC %y SPC %z; + %pieces = getWord($SW::Info[%letter],0); + for (%td = 0; %td < %pieces;%td++) { + %obj = SW_letterPart(%letter,%td,%pos,%matrix,%scale); + %obj.textGroup(%cl,%cl.lastword); + %obj.team = %cl.team; + %obj.needsFit = 1; +// commented out. Can easily remove writing with "remove orphaned pieces", even if client is no longer in game +// %obj.setOwner(0,%cl); + } +} + +function SW_letterPart(%letter,%part,%pos,%matrix,%scale) { + %partInfo = $SW::Sizes[%letter,%part]; + %p1 = SW_goodSquare(%partInfo); + %pos1 = vectorScale(matrixMult(getWords(%p1,0,1) SPC "0",%matrix),%scale); + %vecx1 = vectorScale(matrixMult(getWords(%p1,2,3) SPC "0",%matrix),%scale); + %vecy1 = vectorScale(matrixMult(getWords(%p1,4,5) SPC "0",%matrix),%scale); + %vecz1 = vectorScale(getWords(%matrix,6,8),%scale * $SW::Thickness); + %obj = SW_bar(vectorAdd(%pos,%pos1),%vecx1,%vecy1,%vecz1); + return %obj; +} + +function SW_goodSquare(%p) { + %pos = getWords(%p,0,1); + %x = getWords(%p,2,3); + %y = getWords(%p,4,5); + return %pos SPC getWords(VectorSub(%x,%pos),0,1) SPC getWords(VectorSub(%y,%pos),0,1); +} + +function SW_goodWord(%word) { + %id = 0; + while (%id < strLen(%word)) { + %letter = getSubStr(%word,%id,1); + if (%letter $= "" || %letter $= "/" || %letter $= "+") { + %letter = getSubStr(%word,%id,2); + %id++; + } + if (%letter $= " ") + %letter = "sp"; + %id++; + if (%goodWord !$= "") + %goodWord = %goodWord SPC %letter; + else + %goodWord = %letter; + } + return %goodWord; +} + +//Creates the actual beam +function SW_bar(%pos,%fo,%ri,%up) { + %size = vectorLen(%fo) SPC vectorLen(%ri) SPC vectorLen(%up); + %rot = fullRot(%up,%fo); + + %obj = new StaticShape() { + dataBlock = DeployedSpine; + }; + +// %obj = new ForceFieldBare() { +// datablock = DeployedForceField1; +// }; + + %obj.setRealSize(%size); + %obj.setRotation(%rot); + %pos = microAdjust(%pos); + %obj.setEdge(%pos,"-1 1 -1"); + return %obj; +} + + +///Grouping + +function GameBase::textGroup(%obj,%cl,%word) { + %subGroup = %cl @ "/" @ %word; + %group = nameToID("MissionCleanup/textGroup/" @ %subgroup); + if (%group <= 0) { + %group = new SimGroup(%word); + addToClientTextGroup(%group,%cl); + } + %group.add(%obj); +} + +function addToClientTextGroup(%obj,%cl) { + %group = nameToID("MissionCleanup/textGroup/"@ %cl); + if (%group <= 0) { + %group = new SimGroup(%cl); + addToTextGroup(%group); + } + %group.add(%obj); +} + +function addToTextGroup(%obj) { + %group = nameToID("MissionCleanup/textGroup"); + if (%group <= 0) { + %group = new SimGroup("textGroup"); + MissionCleanup.add(%group); + } + %group.add(%obj); +} + +function getLatestGroup(%group) { + %count = %group.getCount(); + return %group.getObject(%count - 1); +} + +function GameConnection::removeLastWord(%cl) { + %group = nameToID("MissionCleanup/textGroup/" @ %cl); + %lastWord = getLatestGroup(%group); + if (isObject(%lastWord)) + %lastWord.delete(); +} + +function GameConnection::removeWords(%cl) { + %group = nameToID("MissionCleanup/textGroup/" @ %cl); + if (isObject(%group)) + %group.delete(); +} diff --git a/scripts/solitudeBlock.cs b/scripts/solitudeBlock.cs new file mode 100644 index 0000000..0ea2cb4 --- /dev/null +++ b/scripts/solitudeBlock.cs @@ -0,0 +1,117 @@ +function stopBlock(%client,%size,%type) { + %plyr = %client.player; + %pos = pos(%plyr); + %maxRange = 500; + + %className = "ForceFieldBare"; + + if (!%type) + %type = 8; + if (!%size) + %size = 500; + + %planeSize = %size * 2; + + %pieces = mCeil(%planeSize / %maxRange); + %pieceSize = %planeSize / %pieces ; + + %point1 = vectorAdd(%pos, %size SPC %size SPC %size); + %point2 = vectorAdd(%pos, vectorScale(%size SPC %size SPC %size,-1)); +// echo(%pos); +// echo(%point1); +// echo(%point2); + + for (%x =0; %x < %pieces;%x++) { + for (%y =0; %y < %pieces; %y++) { + %topWall = new (%className)() { + dataBlock = DeployedForceField @ %type; + scale = %pieceSize SPC %pieceSize SPC 0.5; + }; + %bottomWall = new (%className)() { + dataBlock = DeployedForceField @ %type; + scale = %pieceSize SPC %pieceSize SPC 0.5; + }; + %eastWall = new (%className)() { + dataBlock = DeployedForceField @ %type; + scale = %pieceSize SPC 0.5 SPC %pieceSize; + }; + %westWall = new (%className)() { + dataBlock = DeployedForceField @ %type; + scale = %pieceSize SPC 0.5 SPC %pieceSize; + }; + %northWall = new (%className)() { + dataBlock = DeployedForceField @ %type; + scale = 0.5 SPC %pieceSize SPC %pieceSize; + }; + %southWall = new (%className)() { + dataBlock = DeployedForceField @ %type; + scale = 0.5 SPC %pieceSize SPC %pieceSize; + }; + %topWall.setTransform(vectorAdd(%point1,-1 * %x * %pieceSize SPC -1 * %y * %pieceSize SPC "0") SPC "0 0 1 3.14"); + %eastWall.setTransform(vectorAdd(%point1,-1 * %x * %pieceSize SPC "0" SPC -1 * %y * %pieceSize) SPC "0 1 0 3.14"); + %northWall.setTransform(vectorAdd(%point1,"0" SPC -1 * %x * %pieceSize SPC -1 * %y * %pieceSize) SPC "1 0 0 3.14"); + %bottomWall.setTransform(vectorAdd(%point2,%x * %pieceSize SPC %y * %pieceSize SPC "0") SPC "0 0 1 0"); + %westWall.setTransform(vectorAdd(%point2,%x * %pieceSize SPC "0" SPC %y * %pieceSize) SPC "0 1 0 0"); + %southWall.setTransform(vectorAdd(%point2,"0" SPC %x * %pieceSize SPC %y * %pieceSize) SPC "1 0 0 0"); + + %topWall.team = %plyr.client.team; + %topWall.setOwner(%plyr); + %topWall.pzone.delete(); + %topWall.addToBlockGroup(); + $TeamDeployedCount[%plyr.team,ForceFieldDeployable]++; + + %eastWall.team = %plyr.client.team; + %eastWall.setOwner(%plyr); + %eastWall.pzone.delete(); + %eastWall.addToBlockGroup(); + $TeamDeployedCount[%plyr.team,ForceFieldDeployable]++; + + %northWall.team = %plyr.client.team; + %northWall.setOwner(%plyr); + %northWall.pzone.delete(); + %northWall.addToBlockGroup(); + $TeamDeployedCount[%plyr.team,ForceFieldDeployable]++; + + %bottomWall.team = %plyr.client.team; + %bottomWall.setOwner(%plyr); + %bottomWall.pzone.delete(); + %bottomWall.addToBlockGroup(); + $TeamDeployedCount[%plyr.team,ForceFieldDeployable]++; + + %westWall.team = %plyr.client.team; + %westWall.setOwner(%plyr); + %westWall.pzone.delete(); + %westWall.addToBlockGroup(); + $TeamDeployedCount[%plyr.team,ForceFieldDeployable]++; + + %southWall.team = %plyr.client.team; + %southWall.setOwner(%plyr); + %southWall.pzone.delete(); + %southWall.addToBlockGroup(); + $TeamDeployedCount[%plyr.team,ForceFieldDeployable]++; + } + } +} + +function ForceFieldBare::addToBlockGroup(%obj) { + %group = nameToID("MissionCleanup/BlockGroup"); + if (%group <= 0) { + %group = new SimGroup("BlockGroup"); + MissionCleanup.add(%group); + } + %group.add(%obj); +} + +function removeBlock() { + %group = nameToID("MissionCleanup/BlockGroup"); + if (!(%group <= 0)) { + %count = %group.getCount(); + for(%i=0;%i<%count;%i++) { + %obj = %group.getObject(%i); + if (%obj) { + $TeamDeployedCount[%obj.team,ForceFieldDeployable]--; + } + } + %group.delete(); + } +} \ No newline at end of file diff --git a/scripts/staticShape.cs b/scripts/staticShape.cs new file mode 100644 index 0000000..86e04c8 --- /dev/null +++ b/scripts/staticShape.cs @@ -0,0 +1,1576 @@ +//****************************************************************************** +//* Default StaticShape functions +//****************************************************************************** + +function shouldChangePowerState(%obj,%state) { + if (%obj.lastState $= "") + return true; + if (%obj.isSwitchedOff == true) + return false; + return %obj.lastState != %state; +} + +function StaticShapeData::onCollision(%data,%obj,%col) { +//general collision funciton made so i dont have to make +//1 function for evry object i want to turn into doors +if (%obj.isdoor !=true && %obj.getdatablock().getname() !$="Deployeddoor") + return; +if (%obj.Collision !=true) + return; +if (%obj.canmove == false) //if it cant move + return; //stop here +if (%col.getClassName() !$= "Player" && %col.getDataBlock().getName() !$= "EscapePodVehicle") + return; +if (%obj.team != %col.team) + return; +if (%obj.islocked == true){ + messageclient(%col.client, 'MsgClient',"Access Denied"); + return; + } +%obj.issliding = 0; +%client = %col.client; +%level = %obj.level; +%owner = %obj.getOwner(); +%ownerguid = %obj.Ownerguid; +//////////////////// +//door level chek // +//////////////////// +if (%obj.lv == 4 && %ownerguid != %client.guid){ + messageclient(%client, 'MsgClient',"Access Denied"@%owner.namebase ); + return; + } +else if (%obj.lv == 5 && %ownerguid != %client.guid && !%client.isadmin){ + messageclient(%client, 'MsgClient',"Access Denied"); + return; + } +//////////////// +//name of door// +//////////////// +else if (%obj.lv == 1) + %lv = "owner"; +else if (%obj.lv == 2) + %lv = "admin"; +else + %lv = "Collision"; + messageclient(%client, 'MsgClient',"Access Granted"); + if (%obj.timeout $="") + %obj.timeout=1; +%obj.closedscale=%obj.scale; + schedule(10,0,"open",%obj); +} + +function StaticShapeData::onGainPowerEnabled(%data,%obj) { +if (!shouldChangePowerState(%obj,true)) +return; +%obj.lastState = true; +if(%data.ambientThreadPowered) +%obj.playThread($AmbientThread, "ambient"); +// if it's a deployed object, schedule the power thread; else play it immediately +if(%data.deployAmbientThread) +%obj.schedule(750, "playThread", $PowerThread, "Power"); +else +%obj.playThread($PowerThread,"Power"); +// deployable objects get their recharge rate set right away -- don't set it again unless +// the object has just been re-enabled +if(%obj.initDeploy) +%obj.initDeploy = false; +else { +if(%obj.getRechargeRate() <= 0) { +if (%data.needsPower) { +%obj.setRechargeRate(%data.rechargeRate + ((%obj.powerCount - 1) * (%data.rechargeRate * 0.5) )); +} +else { +%oldERate = %obj.getRechargeRate(); +%obj.setRechargeRate(%oldERate + %data.rechargeRate); +} +} +} +if(%data.humSound !$= "") +%obj.playAudio($HumSound, %data.humSound); +%obj.setPoweredState(true); +if (%data.className $= "Generator") +checkPowerGenerator(%obj,1); +if (%obj.isdoor == 1 || %obj.getdatablock().getname() $="Deployeddoor") { +if (%obj.canlock == true) //if the door can lock on poweron + %obj.islocked=true; //lock it +if (%obj.canmove == false) //if it cant move + return; //stop here +if (%obj.powercontrol == 1) { + if (%obj.toggletype ==1){ + if (%obj.moving $="close" || %obj.moving $="" || %going $="opening"){ + schedule(10,0,"open",%obj); + } + else if (%obj.moving $="open" || %going $="closeing"){ + schedule(10,0,"close",%obj); + } + } + else + schedule(10,0,"open",%obj); +} +} +} + +function StaticShapeData::onLosePowerDisabled(%data,%obj) { +if (!shouldChangePowerState(%obj,false)) +return; +%obj.lastState = false; +%client = %obj.getControllingClient(); +if(%client != 0) +serverCmdResetControlObject(%client); + +if(%data.ambientThreadPowered) +%obj.pauseThread($AmbientThread); +if(!%data.alwaysAmbient) { +%obj.stopThread($PowerThread); +// MES -- drop shields and stop them from regenerating after power loss +%obj.setRechargeRate(0.0); +%obj.setEnergyLevel(0.0); +} +if(%data.humSound !$= "") +%obj.stopAudio($HumSound); +%obj.setPoweredState(false); +if (%data.className $= "Generator") +checkPowerGenerator(%obj,-1); +if (%obj.isdoor == 1 || %obj.getdatablock().getname() $="Deployeddoor") { +if (%obj.canlock == true) //if the door can lock on poweron + %obj.islocked=false; //unlock it +if (%obj.canmove == false) //if it cant move + return; //stop here +if (%obj.powercontrol == 1) { + if (%obj.toggletype ==1){ + if (%obj.moving $="close" || %obj.moving $="" || %going $="opening"){ + schedule(10,0,"open",%obj); + } + else if (%obj.moving $="open" || %going $="closeing"){ + schedule(10,0,"close",%obj); + } + } + else + schedule(10,0,"open",%obj); +} +} +} + +function StaticShapeData::gainPower(%data,%obj) { + if(%obj.isEnabled()) + %data.onGainPowerEnabled(%obj); + Parent::gainPower(%data,%obj); +} + +function StaticShapeData::losePower(%data,%obj) { + if(%obj.isEnabled()) + %data.onLosePowerDisabled(%obj); + Parent::losePower(%data,%obj); +} + +function ShapeBaseData::onEnabled() +{ +} + +function ShapeBaseData::onDisabled() +{ +} + +function StaticShapeData::onEnabled(%data, %obj, %prevState) { + if(%obj.isPowered()) + %data.onGainPowerEnabled(%obj); + Parent::onEnabled(%data, %obj, %prevState); +} + +function StaticShapeData::onDisabled(%data, %obj, %prevState) { + if(%obj.isPowered() || (%data.className $= "Generator")) + %data.onLosePowerDisabled(%obj); + Parent::onDisabled(%data, %obj, %prevState); +} + +function StaticShape::deploy(%this) +{ + %this.playThread($DeployThread, "deploy"); +} + +function StaticShapeData::onEndSequence(%data, %obj, %thread) +{ + if(%thread == $DeployThread && !%data.needsPower) + %obj.setSelfPowered(); + Parent::onEndSequence(%data, %obj, %thread); +} + +function ShapeBaseData::onEndSequence() +{ +} + +//****************************************************************************** +//* Example explosion +//****************************************************************************** + +datablock EffectProfile(ShapeExplosionEffect) +{ + effectname = "explosions/explosion.xpl03"; + minDistance = 10; + maxDistance = 50; +}; + +datablock AudioProfile(ShapeExplosionSound) +{ + filename = "fx/explosions/explosion.xpl03.wav"; + description = AudioExplosion3d; + preload = true; + effect = ShapeExplosionEffect; +}; + +datablock ExplosionData(ShapeExplosion) +{ + explosionShape = "disc_explosion.dts"; + soundProfile = ShapeExplosionSound; + faceViewer = true; +}; + +//****************************************************************************** +//* Player Armors - Data Blocks (live players are now StaticTSObjects) +//****************************************************************************** + +datablock StaticShapeData(HeavyMaleHuman_Dead) +{ + className = "deadArmor"; + catagory = "Player Armors"; + shapeFile = "heavy_male_dead.dts"; + isInvincible = true; +}; + +datablock StaticShapeData(MediumMaleHuman_Dead) +{ + className = "deadArmor"; + catagory = "Player Armors"; + shapeFile = "medium_male_dead.dts"; + isInvincible = true; +}; + +datablock StaticShapeData(LightMaleHuman_Dead) +{ + className = "deadArmor"; + catagory = "Player Armors"; + shapeFile = "light_male_dead.dts"; + isInvincible = true; +}; + +function deadArmor::onAdd(%data, %obj) +{ + Parent::onAdd(%data, %obj); +} + +//***************************************************************************** +//* Flagstands - Data Blocks +//***************************************************************************** +datablock StaticShapeData(InteriorFlagStand) +{ + className = "FlagIntStand"; + catagory = "Objectives"; + shapefile = "int_flagstand.dts"; + isInvincible = true; + needsNoPower = true; +}; + +datablock StaticShapeData(ExteriorFlagStand) +{ + className = "FlagIntStand"; + catagory = "Objectives"; + shapefile = "ext_flagstand.dts"; + isInvincible = true; + needsNoPower = true; +}; + +/////////////////////////////////////////// +//flagIntStand::onAdd(%this, %obj) +//%this: objects datablock +//%obj: the actual object being added +/////////////////////////////////////////// + +function ExteriorFlagStand::onAdd(%this, %obj) +{ + Parent::onAdd(%this, %obj); + %obj.playThread($ActivateThread, "activate"); +} + +function ExteriorFlagStand::onFlagTaken(%this, %obj) +{ + %obj.setThreadDir($ActivateThread, 0); +} + +function ExteriorFlagStand::onFlagReturn(%this, %obj) +{ + %obj.setThreadDir($ActivateThread, 1); +} + +function ExteriorFlagStand::onCollision(%this, %obj, %colObj) +{ + game.flagStandCollision(%this, %obj, %colObj); +} + +function InteriorFlagStand::onCollision(%this, %obj, %colObj) +{ + game.flagStandCollision(%this, %obj, %colObj); +} + +/////////////////////////////////////////////// +//end flag stand functions +/////////////////////////////////////////////// + +datablock StaticShapeData(FlipFlop) +{ + catagory = "Objectives"; + shapefile = "switch.dts"; + + isInvincible = true; + cmdCategory = "Objectives"; + cmdIcon = "CMDSwitchIcon"; + cmdMiniIconName = "commander/MiniIcons/com_switch_grey"; + targetTypeTag = 'Switch'; + alwaysAmbient = true; + needsNoPower = true; + emap = true; +}; + +function FlipFlop::onCollision(%data,%obj,%col) +{ + if (%col.getDataBlock().className $= Armor && %col.getState() !$= "Dead") + %data.playerTouch(%obj, %col); +} + +function FlipFlop::playerTouch(%data,%obj,%col) +{ + messageAll('MsgPlayerTouchSwitch', 'Player %1 touched switch %2', %col, %obj); +} + +//****************************************************************************** +//* Organics - * +//****************************************************************************** + +//function to add random Organics to mission pre-creation +//(could be used to add other things...its cool with bioderm armors ;) ) + +function randomOrg(%organicName, %num, %radius) +{ + %SPACING = 1.0; //meters between center of organic and another object + + //return help info + if(%organicName $="" || !%num || !%radius) { + echo("randomOrg(, , );"); + return; + } + + %organicIndex = -1; + // -------------------------------------------------------- + // z0dd - ZOD, 5/8/02. Typo fix. + //for (%i = 0; %i < $NumAStaticTSObjects; %i++) { + for (%i = 0; %i < $NumStaticTSObjects; %i++) { + if (getWord($StaticTSObjects[%i], 1) $= %organicName) { + %organicIndex = %i; + break; + } + } + if (%organicIndex == -1) { + error("There is no static shape named" SPC %organicName); + return; + } + %shapeFileName = getWord($StaticTSObjects[%organicIndex], 2); + + %maxSlope = getWord($StaticTSObjects[%organicIndex], 3); + if (%maxSlope $= "") + %maxSlope = 40; + + %zOffset = getWord($StaticTSObjects[%organicIndex], 4); + if (%zOffset $= "") + %zOffset = 0; + + %slopeWithTerrain = getWord($StaticTSObjects[%organicIndex], 5); + if (%slopeWithTerrain $= "") + %slopeWithTerrain = false; + + %minScale = getWord($StaticTSObjects[%organicIndex], 6); + %maxScale = getWord($StaticTSObjects[%organicIndex], 7); + + //set up folders in mis file + $RandomOrganicsAdded++; //to keep track of groups + if(!isObject(RandomOrganics)) { + %randomOrgGroup = new simGroup(RandomOrganics); + MissionGroup.add(%randomOrgGroup); + } + %groupName = "Addition"@$RandomOrganicsAdded@%organicName; + %group = new simGroup(%groupName); + RandomOrganics.add(%group); + + + %ctr = LocalClientConnection.camera.getPosition(); + %areaX = getWord(%ctr, 0) - %radius; + %areaY = getWord(%ctr, 1) - %radius; + + %orgCount = %num; + while((%orgCount > 0) && (%retries < (15000 / %maxSlope))) //theoretically, a thorough number of retries + { + //find a tile + %x = (getRandom(mFloor(%areaX / 8), mFloor((%areaX + (%radius * 2)) / 8)) * 8) + 4; //tile center + %y = (getRandom(mFloor(%areaY / 8), mFloor((%areaY + (%radius * 2)) / 8)) * 8) + 4; + + %start = %x @ " " @ %y @ " 2000"; + %end = %x @ " " @ %y @ " -1"; + %ground = containerRayCast(%start, %end, $TypeMasks::TerrainObjectType, 0); + %z = getWord(%ground, 3); + %z += %zOffset; + %position = %x @ " " @ %y @ " " @ %z; + + + // get normal from both sides of the square + %start = %x + 2 @ " " @ %y @ " 2000"; + %end = %x + 2 @ " " @ %y @ " -1"; + %hit1 = containerRayCast(%start, %end, $TypeMasks::TerrainObjectType, 0); + + %start = %x - 2 @ " " @ %y @ " 2000"; + %end = %x - 2 @ " " @ %y @ " -1"; + %hit2 = containerRayCast(%start, %end, $TypeMasks::TerrainObjectType, 0); + + %norm1 = getWord(%hit1, 4) @ " " @ getWord(%hit1, 5) @ " " @ getWord(%hit1, 6); + %norm2 = getWord(%hit2, 4) @ " " @ getWord(%hit2, 5) @ " " @ getWord(%hit2, 6); + + //if either side of tile has greater slope than allowed, move on. + %angNorm1 = getTerrainAngle(%norm1); + %angNorm2 = getTerrainAngle(%norm2); + if ((getTerrainAngle(%norm1) > %maxSlope) || (getTerrainAngle(%norm2) > %maxslope)) + { + %retries++; + continue; + } + + %terrainNormal = VectorAdd(%norm1, %norm2); + %terrainNormal = VectorNormalize(%terrainNormal); + + //search surroundings for obstacles. If obstructed, move on. + InitContainerRadiusSearch(%position, %spacing, $TypeMasks::VehicleObjectType | + $TypeMasks::MoveableObjectType | + $TypeMasks::StaticShapeObjectType | + // ----------------------------- + // z0dd - ZOD, 5/8/02. Typo fix. + //$TypeMasks::TSStaticShapeObjectType | + $TypeMasks::StaticTSObjectType | + $TypeMasks::ForceFieldObjectType | + $TypeMasks::TurretObjectType | + $TypeMasks::InteriorObjectType | + $TypeMasks::ItemObjectType); + %this = containerSearchNext(); + if(%this) + { + %retries++; + continue; + } + + + //rotate it + if(%slopeWithTerrain) + { + %rotAxis = vectorCross(%terrainNormal, "0 0 1"); + %rotAxis = vectorNormalize(%rotAxis); + %rotation = %rotAxis @ " " @ getTerrainAngle(%terrainNormal); + } + else %rotation = "1 0 0 0"; + %randomAngle = getRandom(360); + %zrot = MatrixCreate("0 0 0", "0 0 1 " @ %randomAngle); + %orient = MatrixCreate(%position, %rotation); + %finalXForm = validateVal(MatrixMultiply(%orient, %zrot)); + + + //scale it + %scaleMin = 8; //default min + %scaleMax = 14; //default max + if(%minScale) + %scaleMin = %minScale * 10; + if(%maxScale) + %scaleMax = %maxScale * 10; + %scaleInt = getRandom(%scaleMin, %scaleMax); + %scale = %scaleInt/10; + %evenScale = %scale SPC %scale SPC %scale; + + //create it + %position = %x SPC %y SPC (%z += %zoffset); + %newOrganic = new TSStatic() { + position = %position; + rotation = %rotation; + scale = %evenScale; + shapeName = %shapeFileName; + }; + %group.add(%newOrganic); + %newOrganic.setTransform(%finalXForm); + + %orgCount--; //dec number of shapes left to place + %retries = 0; //reset retry counter + } + if (%orgCount > 0) + { + error("Unable to place all shapes, area saturated."); + error("Looking for clear area " @ (%spacing * 2) @ " meters in diameter, with a max slope of " @ %maxSlope); + } + echo("Placed " @ %num - %orgCount @ " of " @ %num); +} + +function getTerrainAngle(%point) +{ + %up = "0 0 1"; + %angleRad = mACos(vectorDot(%point, %up)); + %angleDeg = mRadToDeg(%angleRad); + //echo("angle is "@%angleDeg); + return %angleDeg; +} +function randomGrove(%organicName, %num, %radius) +{ + %minHeight = 0; + %maxHeight = 1000; + %SPACING = 1.5; //meters between center of organic and another object + + //return help info + if(%organicName $="" || !%num || !%radius) { + echo("randomOrg(, [, radius of grove desired]);"); + return; + } + + %organicIndex = -1; + for (%i = 0; %i < $NumStaticTSObjects; %i++) { + if (getWord($StaticTSObjects[%i], 1) $= %organicName) { + %organicIndex = %i; + break; + } + } + if (%organicIndex == -1) { + error("There is no static shape named" SPC %organicName); + return; + } + %shapeFileName = getWord($StaticTSObjects[%organicIndex], 2); + + %maxSlope = getWord($StaticTSObjects[%organicIndex], 3); + if (%maxSlope $= "") + %maxSlope = 40; + + %zOffset = getWord($StaticTSObjects[%organicIndex], 4); + if (%zOffset $= "") + %zOffset = 0; + + %slopeWithTerrain = getWord($StaticTSObjects[%organicIndex], 5); + if (%slopeWithTerrain $= "") + %slopeWithTerrain = false; + + %minScale = getWord($StaticTSObjects[%organicIndex], 6); + %maxScale = getWord($StaticTSObjects[%organicIndex], 7); + + //set up folders in mis file + $RandomOrganicsAdded++; //to keep track of groups + if(!isObject(RandomOrganics)) { + %randomOrgGroup = new simGroup(RandomOrganics); + MissionGroup.add(%randomOrgGroup); + } + %groupName = "Addition"@$RandomOrganicsAdded@%organicName; + %group = new simGroup(%groupName); + RandomOrganics.add(%group); + + + %ctr = LocalClientConnection.camera.getPosition(); + %areaX = getWord(%ctr, 0) - %radius; + %areaY = getWord(%ctr, 1) - %radius; + + %orgCount = %num; + while((%orgCount > 0) && (%retries < (15000 / %maxSlope))) //theoretically, a thorough number of retries + { + //find a tile + %x = (getRandom(mFloor(%areaX / 8), mFloor((%areaX + (%radius * 2)) / 8)) * 8) + 4; //tile center + %y = (getRandom(mFloor(%areaY / 8), mFloor((%areaY + (%radius * 2)) / 8)) * 8) + 4; + + %start = %x @ " " @ %y @ " 2000"; + %end = %x @ " " @ %y @ " -1"; + %ground = containerRayCast(%start, %end, $TypeMasks::TerrainObjectType, 0); + %z = getWord(%ground, 3); + + + // elevation test + if ((%z < %minHeight) || (%z > %maxHeight)) + { + echo("Broke height range rules. Readjust allowable elevations."); + %retries++; + echo("Z is " @ %z); + continue; + } + %z += %zOffset; + %position = %x @ " " @ %y @ " " @ %z; + + + // get normal from both sides of the square + %start = %x + 2 @ " " @ %y @ " 2000"; + %end = %x + 2 @ " " @ %y @ " -1"; + %hit1 = containerRayCast(%start, %end, $TypeMasks::TerrainObjectType, 0); + + %start = %x - 2 @ " " @ %y @ " 2000"; + %end = %x - 2 @ " " @ %y @ " -1"; + %hit2 = containerRayCast(%start, %end, $TypeMasks::TerrainObjectType, 0); + + %norm1 = getWord(%hit1, 4) @ " " @ getWord(%hit1, 5) @ " " @ getWord(%hit1, 6); + %norm2 = getWord(%hit2, 4) @ " " @ getWord(%hit2, 5) @ " " @ getWord(%hit2, 6); + + //if either side of tile has greater slope than allowed, move on. + %angNorm1 = getTerrainAngle(%norm1); + %angNorm2 = getTerrainAngle(%norm2); + if ((getTerrainAngle(%norm1) > %maxSlope) || (getTerrainAngle(%norm2) > %maxslope)) + { + %retries++; + continue; + } + + %terrainNormal = VectorAdd(%norm1, %norm2); + %terrainNormal = VectorNormalize(%terrainNormal); + + //search surroundings for obstacles. If obstructed, move on. + InitContainerRadiusSearch(%position, %spacing, $TypeMasks::VehicleObjectType | + $TypeMasks::MoveableObjectType | + $TypeMasks::StaticShapeObjectType | + // ----------------------------- + // z0dd - ZOD, 5/8/02. Typo fix. + //$TypeMasks::TSStaticShapeObjectType | + $TypeMasks::StaticTSObjectType | + $TypeMasks::ForceFieldObjectType | + $TypeMasks::TurretObjectType | + $TypeMasks::InteriorObjectType | + $TypeMasks::ItemObjectType); + %this = containerSearchNext(); + if(%this) + { + %retries++; + continue; + } + + + //rotate it + if(%slopeWithTerrain) + { + %rotAxis = vectorCross(%terrainNormal, "0 0 1"); + %rotAxis = vectorNormalize(%rotAxis); + %rotation = %rotAxis @ " " @ getTerrainAngle(%terrainNormal); + } + else %rotation = "1 0 0 0"; + %randomAngle = getRandom(360); + %zrot = MatrixCreate("0 0 0", "0 0 1 " @ %randomAngle); + %orient = MatrixCreate(%position, %rotation); + %finalXForm = validateVal(MatrixMultiply(%orient, %zrot)); + + + //scale it + %scaleMin = 8; //default min + %scaleMax = 14; //default max + if(%minScale) + %scaleMin = %minScale * 10; + if(%maxScale) + %scaleMax = %maxScale * 10; + %scaleInt = getRandom(%scaleMin, %scaleMax); + %scale = %scaleInt/10; + %evenScale = %scale SPC %scale SPC %scale; + + //create it + + %position = %x SPC %y SPC (%z += %zoffset); + %newOrganic = new TSStatic() { + position = %position; + rotation = %rotation; + scale = %evenScale; + shapeName = %shapeFileName; + }; + %group.add(%newOrganic); + %newOrganic.setTransform(%finalXForm); + + %orgCount--; //dec number of shapes left to place + %retries = 0; //reset retry counter + } + if (%orgCount > 0) + { + error("Unable to place all shapes, area saturated."); + error("Looking for clear area " @ (%spacing * 2) @ " meters in diameter, with a max slope of " @ %maxSlope); + } + echo("Placed " @ %num - %orgCount @ " of " @ %num); +} + + +function randomRock(%rock, %quantity, %radius, %maxElev) +{ + if (!%radius || !%quantity || !%rock) + { + echo("randomRock(, , , [maximum elevation]"); + return; + } + + if (!%maxElev) + %maxElev = 2000; + + + %rotation[0] = "0 0 1 0"; + %rotation[1] = "0.999378 -0.0145686 -0.0321219 194.406"; + %rotation[2] = "0.496802 0.867682 0.0177913 176.44"; + %rotation[3] = "0.991261 0.0933696 0.0931923 181.867"; + %rotation[4] = "0.246801 0.360329 -0.899584 92.3648"; + %rotation[5] = "1 0 0 82.59"; + %rotation[6] = "0.0546955 -0.629383 0.55201 116.103"; + + %spacing = 4.0; //check 4 meters around object for collisions before placing + %ctr = localClientConnection.camera.getPosition(); + %areaX = getWord(%ctr, 0) - %radius; + %areaY = getWord(%ctr, 1) - %radius; + + $RandomOrganicsAdded++; + if(!isObject(RandomRocks)) { + %randomOrgGroup = new simGroup(RandomRocks); + MissionGroup.add(%randomOrgGroup); + } + %groupName = "Addition"@$RandomOrganicsAdded@%rock; + %group = new simGroup(%groupName); + RandomRocks.add(%group); + + %orgCount = %quantity; + while((%orgCount > 0) && (%retries < (15000 / %maxSlope))) //theoretically, a thorough number of retries + { + //find a tile + %x = %areaX + getRandom(%radius * 2); + %y = %areaY + getRandom(%radius * 2); + + %start = %x @ " " @ %y @ " 2000"; + %end = %x @ " " @ %y @ " -1"; + %ground = containerRayCast(%start, %end, $TypeMasks::TerrainObjectType, 0); + %position = getWord(%ground, 1) @ " " @ getWord(%ground, 2) @ " " @ getWord(%ground, 3); + echo("position =*" @ %position @ "*"); + %z = getWord(%position, 2); + + + // elevation test + if (%z > %maxElev) //65 meters and above only + { + %retries++; + echo("Z is " @ %z); + continue; + } + + + //search surroundings for obstacles. If obstructed, move on. + InitContainerRadiusSearch(%position, %spacing, $TypeMasks::VehicleObjectType | + $TypeMasks::MoveableObjectType | + $TypeMasks::StaticShapeObjectType | + // ----------------------------- + // z0dd - ZOD, 5/8/02. Typo fix. + //$TypeMasks::TSStaticShapeObjectType | + $TypeMasks::StaticTSObjectType | + $TypeMasks::ForceFieldObjectType | + $TypeMasks::TurretObjectType | + $TypeMasks::InteriorObjectType | + $TypeMasks::ItemObjectType); + %this = containerSearchNext(); + if(%this) + { + %retries++; + continue; + } + %primaryRot = %rotation[getRandom(7)]; + + %randomAngle = mDegToRad(getRandom(360)); + %zrot = MatrixCreate("0 0 0", "0 0 1 " @ %randomAngle); + %orient = MatrixCreate(%position, %primaryRot); + + + %scale = getRandom(3); + %evenScale = %scale @ " " @ %scale @ " " @ %scale; + %newRock = new InteriorInstance() { + scale = %evenScale; + interiorFile = %rock @ ".dif"; + showTerrainInside = "0"; + }; + %group.add(%newRock); + %transfrm = validateVal(MatrixMultiply(%orient, %zrot)); + echo("Transform = *" @ %transfrm @ "*"); + %newRock.setTransform(%transfrm); + + %orgCount--; //dec number of shapes left to place + %retries = 0; //reset retry counter + } + if (%orgCount > 0) + { + error("Unable to place all shapes, area saturated."); + error("Looking for clear area " @ (%spacing * 2) @ " meters in diameter, with a max slope of " @ %maxSlope); + } + echo("Placed " @ %num - %orgCount @ " of " @ %num); +} + + +//-------------------------------------------------------------------------- +//-------------------------------------- Organics +//-------------------------------------------------------------------------- + + +//****************************************************************************** +//* Pulse Sensor - Data Blocks * +//****************************************************************************** + +datablock DebrisData( StaticShapeDebris ) +{ + explodeOnMaxBounce = false; + + elasticity = 0.20; + friction = 0.5; + + lifetime = 17.0; + lifetimeVariance = 0.0; + + minSpinSpeed = 60; + maxSpinSpeed = 600; + + numBounces = 10; + bounceVariance = 0; + + staticOnMaxBounce = true; + + useRadiusMass = true; + baseRadius = 0.4; + + velocity = 9.0; + velocityVariance = 4.5; +}; + +datablock DebrisData( SmallShapeDebris ) +{ + explodeOnMaxBounce = false; + + elasticity = 0.20; + friction = 0.5; + + lifetime = 17.0; + lifetimeVariance = 0.0; + + minSpinSpeed = 60; + maxSpinSpeed = 600; + + numBounces = 10; + bounceVariance = 0; + + staticOnMaxBounce = true; + + useRadiusMass = true; + baseRadius = 0.2; + + velocity = 5.0; + velocityVariance = 2.5; +}; + +datablock AudioProfile(SensorHumSound) +{ + filename = "fx/powered/sensor_hum.wav"; + description = CloseLooping3d; + preload = true; +}; + +datablock SensorData(SensorLgPulseObj) +{ + detects = true; + detectsUsingLOS = true; + detectsPassiveJammed = false; + detectsActiveJammed = false; + detectsCloaked = false; + detectionPings = true; + detectRadius = 300; +}; + +datablock StaticShapeData(SensorLargePulse) : StaticShapeDamageProfile +{ + className = Sensor; + catagory = "Sensors"; + shapeFile = "sensor_pulse_large.dts"; + maxDamage = 1.5; + destroyedLevel = 1.5; + disabledLevel = 0.85; + explosion = ShapeExplosion; + expDmgRadius = 10.0; + expDamage = 0.5; + expImpulse = 2000.0; + repairRate = 0.5; + + dynamicType = $TypeMasks::SensorObjectType; + isShielded = true; + energyPerDamagePoint = 33; + maxEnergy = 110; + rechargeRate = 0.31; + ambientThreadPowered = true; + humSound = SensorHumSound; + + cmdCategory = "Support"; + cmdIcon = CMDSensorIcon; + cmdMiniIconName = "commander/MiniIcons/com_sensor_grey"; + targetNameTag = 'Large'; + targetTypeTag = 'Sensor'; + sensorData = SensorLgPulseObj; + sensorRadius = SensorLgPulseObj.detectRadius; + sensorColor = "255 194 9"; + + debrisShapeName = "debris_generic.dts"; + debris = StaticShapeDebris; + needsPower = true; +}; + +datablock SensorData(SensorMedPulseObj) +{ + detects = true; + detectsUsingLOS = true; + detectsPassiveJammed = false; + detectsActiveJammed = false; + detectsCloaked = false; + detectionPings = true; + detectRadius = 200; +}; + +datablock StaticShapeData(SensorMediumPulse) : StaticShapeDamageProfile +{ + className = Sensor; + catagory = "Sensors"; + shapeFile = "sensor_pulse_medium.dts"; + maxDamage = 1.2; + destroyedLevel = 1.2; + disabledLevel = 0.68; + explosion = ShapeExplosion; + expDmgRadius = 7.0; + expDamage = 0.4; + expImpulse = 1500; + repairRate = 0.5; + + dynamicType = $TypeMasks::SensorObjectType; + isShielded = true; + energyPerDamagePoint = 33; + maxEnergy = 90; + rechargeRate = 0.31; + ambientThreadPowered = true; + humSound = SensorHumSound; + + cmdCategory = "Support"; + cmdIcon = CMDSensorIcon; + cmdMiniIconName = "commander/MiniIcons/com_sensor_grey"; + targetNameTag = 'Medium'; + targetTypeTag = 'Sensor'; + sensorData = SensorMedPulseObj; + sensorRadius = SensorMedPulseObj.detectRadius; + sensorColor = "255 194 9"; + + debrisShapeName = "debris_generic.dts"; + debris = StaticShapeDebris; + needsPower = true; +}; + +function Sensor::onGainPowerEnabled(%data, %obj) +{ + setTargetSensorData(%obj.target, %data.sensorData); + Parent::onGainPowerEnabled(%data, %obj); +} + +function Sensor::onLosePowerDisabled(%data, %obj) +{ + setTargetSensorData(%obj.target, 0); + Parent::onLosePowerDisabled(%data, %obj); +} + +//****************************************************************************** +//* Generator - Data Blocks * +//****************************************************************************** + +datablock AudioProfile(GeneratorHumSound) +{ + filename = "fx/powered/generator_hum.wav"; + description = CloseLooping3d; + preload = true; +}; + + +datablock StaticShapeData(GeneratorLarge) : StaticShapeDamageProfile +{ + className = Generator; + catagory = "Generators"; + shapeFile = "station_generator_large.dts"; + explosion = ShapeExplosion; + maxDamage = 1.50; + destroyedLevel = 1.50; + disabledLevel = 0.85; + expDmgRadius = 10.0; + expDamage = 0.5; + expImpulse = 1500.0; + noIndividualDamage = true; //flag to make these invulnerable for certain mission types + + dynamicType = $TypeMasks::GeneratorObjectType; + isShielded = true; + energyPerDamagePoint = 30; + maxEnergy = 50; + rechargeRate = 0.05; + humSound = GeneratorHumSound; + + cmdCategory = "Support"; + cmdIcon = "CMDGeneratorIcon"; + cmdMiniIconName = "commander/MiniIcons/com_generator"; + targetTypeTag = 'Generator'; + + debrisShapeName = "debris_generic.dts"; + debris = StaticShapeDebris; + powerRadius = 100; +}; + +datablock StaticShapeData(SolarPanel) : StaticShapeDamageProfile +{ + className = Generator; + catagory = "Generators"; + shapeFile = "solarpanel.dts"; + explosion = ShapeExplosion; + maxDamage = 1.00; + destroyedLevel = 1.00; + disabledLevel = 0.55; + expDmgRadius = 5.0; + expDamage = 0.3; + expImpulse = 1000.0; + noIndividualDamage = true; //flag to make these invulnerable for certain mission types + emap = true; + + isShielded = true; + energyPerDamagePoint = 30; + rechargeRate = 0.05; + + dynamicType = $TypeMasks::GeneratorObjectType; + maxEnergy = 30; + humSound = GeneratorHumSound; + + cmdCategory = "Support"; + cmdIcon = CMDSolarGeneratorIcon; + cmdMiniIconName = "commander/MiniIcons/com_solargen_grey"; + targetTypeTag = 'Solar Panel'; + + debrisShapeName = "debris_generic.dts"; + debris = StaticShapeDebris; + powerRadius = 50; +}; + +function Generator::onDisabled(%data, %obj, %prevState) { + %obj.decPowerCount(); + Parent::onDisabled(%data, %obj, %prevState); +} + +function Generator::onEnabled(%data, %obj, %prevState) { + %obj.incPowerCount(); + Parent::onEnabled(%data, %obj, %prevState); +} + +//****************************************************************************** +//Nexus Effect (Hunters) +//****************************************************************************** + +datablock StaticShapeData(Nexus_Effect) +{ + catagory = "Objectives"; + shapefile = "nexus_effect.dts"; + mass = 10; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 2; +}; + + +datablock StaticShapeData(NexusBase) +{ + catagory = "Objectives"; + shapefile = "Nexusbase.dts"; + mass = 10; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 2; +}; + + +datablock StaticShapeData(NexusCap) +{ + catagory = "Objectives"; + shapefile = "Nexuscap.dts"; + mass = 10; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 2; +}; + +//****************************************************************************** +//* Static Shape - Functions * +//****************************************************************************** + +function StaticShapeData::create(%block) +{ + %obj = new StaticShape() + { + dataBlock = %block; + }; + return(%obj); +} + +function ShapeBase::damage(%this, %sourceObject, %position, %amount, %damageType) +{ + %this.getDataBlock().damageObject(%this, %sourceObject, %position, %amount, %damageType); +} + +function ShapeBaseData::damageObject(%data, %targetObject, %position, %sourceObject, %amount, %damageType) +{ + +} + +function ShapeBaseData::onDestroyed(%data, %obj, %prevState) +{ + +} + +function ShapeBaseData::checkShields(%data, %targetObject, %position, %amount, %damageType) +{ + %energy = %targetObject.getEnergyLevel(); + %strength = %energy / %data.energyPerDamagePoint; + %shieldScale = %data.shieldDamageScale[%damageType]; + if(%shieldScale $= "") + %shieldScale = 1; + + if (%amount * %shieldScale <= %strength) { + // Shield absorbs all + %lost = %amount * %shieldScale * %data.energyPerDamagePoint; + %energy -= %lost; + %targetObject.setEnergyLevel(%energy); + + %normal = "0.0 0.0 1.0"; + %targetObject.playShieldEffect( %normal ); + + return 0; + } + // Shield exhausted + %targetObject.setEnergyLevel(0); + return %amount - %strength / %shieldScale; +} + +function StaticShapeData::damageObject(%data, %targetObject, %sourceObject, %position, %amount, %damageType) { + if (%targetObject.getType() & $TypeMasks::ForceFieldObjectType) + %isFF = true; + if (%targetObject.getType() & $TypeMasks::TurretObjectType) + %isTurret = true; + if ($Host::InvincibleDeployables == 1) { + if (%targetObject.getGroup() == Deployables.getID() + && !%data.powerRadius + && %data != StationInventory.getID() + && !%isFF + && !%isTurret) + return; + } + if (isObject(%sourceObject)) + if (%sourceObject.getType() & $TypeMasks::VehicleObjectType) + if (%sourceObject.getDataBlock() == EscapePodVehicle.getID()) { + // Reverse damage ;) + %tmp = %sourceObject; + %sourceObject = %targetObject; + %targetObject = %tmp; + } + + if (%targetObject.lTarget) { + if (isObject(%targetObject.lTarget)) { + return; + } + } + else if (%targetObject.lMain) { + if (isObject(%targetObject.lMain)) { + %targetObject = %targetObject.lMain; + } + } + + // if this is a non-team mission type and the object is "protected", don't damage it + if(%data.noIndividualDamage && Game.allowsProtectedStatics() && !%targetObject.deployed) + return; + + // if this is a Siege mission and this object shouldn't take damage (e.g. vehicle stations) + if(%data.noDamageInSiege && Game.class $= "SiegeGame") + return; + + // Don't let deployed turrets damage other deployed items of the same team + if (isObject(%sourceObject) && isObject(%targetObject)) { + if ((%targetObject.getDataBlock().deployedObject || %targetObject.deployed) + && (%sourceObject.getType() & $TypeMasks::TurretObjectType) + && %sourceObject.team == %targetObject.team) + return; + } + + // Switch to not let deployed turrets damage any deployed item of any team + if (isObject(%sourceObject) && isObject(%targetObject) && $NoTurretDamage == 1) { + if ((%targetObject.getDataBlock().deployedObject || %targetObject.deployed) + && (%sourceObject.getType() & $TypeMasks::TurretObjectType)) + return; + } + + if(%sourceObject && %targetObject.isEnabled()) + { + if(%sourceObject.client) + { + %targetObject.lastDamagedBy = %sourceObject.client; + %targetObject.lastDamagedByTeam = %sourceObject.client.team; + %targetObject.damageTimeMS = GetSimTime(); + } + else + { + %targetObject.lastDamagedBy = %sourceObject; + %targetObject.lastDamagedByTeam = %sourceObject.team; + %targetObject.damageTimeMS = GetSimTime(); + } + } + + // Scale damage type & include shield calculations... + if (%data.isShielded) + %amount = %data.checkShields(%targetObject, %position, %amount, %damageType); + + %damageScale = %data.damageScale[%damageType]; + if(%damageScale !$= "") + %amount *= %damageScale; + + //if team damage is off, cap the amount of damage so as not to disable the object... + if (!$TeamDamage && !%targetObject.getDataBlock().deployedObject) { + // ------------------------------------- + // z0dd - ZOD, 6/24/02. Console spam fix + if(isObject(%sourceObject)) { + //see if the object is being shot by a friendly + if(%sourceObject.getDataBlock().catagory $= "Vehicles") + %attackerTeam = getVehicleAttackerTeam(%sourceObject); + else + %attackerTeam = %sourceObject.team; + } + if (((%targetObject.getTarget() != -1) && isTargetFriendly(%targetObject.getTarget(), %attackerTeam)) && !%isFF) { + %curDamage = %targetObject.getDamageLevel(); + %availableDamage = %targetObject.getDataBlock().disabledLevel - %curDamage - 0.05; + if (%amount > %availableDamage) + %amount = %availableDamage; + } + } + + // if there's still damage to apply + if (%amount > 0) { + if (%isFF) + %targetObject.applyDamage(%amount,%sourceObject,%position,%damageType); + else + %targetObject.applyDamage(%amount); + } +} + +// little special casing for the above function +function getVehicleAttackerTeam(%vehicleId) +{ + %name = %vehicleId.getDataBlock().getName(); + if(%name $= "BomberFlyer" || %name $= "AssaultVehicle") + %gunner = %vehicleId.getMountNodeObject(1); + else + %gunner = %vehicleId.getMountNodeObject(0); + + if(%gunner) + return %gunner.team; + + return %vehicleId.team; +} + +function StaticShapeData::onDamage(%this,%obj) { + // Set damage state based on current damage level + %damage = %obj.getDamageLevel(); + if(%damage >= %this.destroyedLevel) { + if(%obj.getDamageState() !$= "Destroyed") { + %obj.setDamageState(Destroyed); + // if object has an explosion damage radius associated with it, apply explosion damage + if(%this.expDmgRadius) { + RadiusExplosion(%obj, %obj.getWorldBoxCenter(), %this.expDmgRadius, %this.expDamage, %this.expImpulse, %obj, $DamageType::Explosion); + %obj.hasExploded = true; + } + %obj.setDamageLevel(%this.maxDamage); + } + } + else { + if(%damage >= %this.disabledLevel) { + if(%obj.getDamageState() !$= "Disabled") + %obj.setDamageState(Disabled); + } + else { + if(%obj.getDamageState() !$= "Enabled") + %obj.setDamageState(Enabled); + } + } +} + +function StaticShapeData::onDestroyed(%data,%obj,%prevState) { + if(%data.expDmgRadius && !%obj.hasExploded) { + RadiusExplosion(%obj, %obj.getWorldBoxCenter(), %data.expDmgRadius, %data.expDamage, %data.expImpulse, %obj, $DamageType::Explosion); + %obj.hasExploded = true; + } + Parent::onDestroyed(%data,%obj,%prevState); +} + +// -------------------------------------------------------------------- +// Team logos - only the logo projector should be placed in a mission + +datablock StaticShapeData(BaseLogo) //storm logo +{ + className = Logo; + shapeFile = "teamlogo_storm.dts"; + alwaysAmbient = true; +}; + +datablock StaticShapeData(BaseBLogo) //Inferno Logo +{ + className = Logo; + shapeFile = "teamlogo_inf.dts"; + alwaysAmbient = true; +}; + +datablock StaticShapeData(BiodermLogo) +{ + className = Logo; + shapeFile = "teamlogo_bd.dts"; + alwaysAmbient = true; +}; + +datablock StaticShapeData(BEagleLogo) +{ + className = Logo; + shapeFile = "teamlogo_be.dts"; + alwaysAmbient = true; +}; + +datablock StaticShapeData(DSwordLogo) +{ + className = Logo; + shapeFile = "teamlogo_ds.dts"; + alwaysAmbient = true; +}; + +datablock StaticShapeData(COTPLogo) +{ + className = Logo; + shapeFile = "teamlogo_hb.dts"; + alwaysAmbient = true; +}; + +datablock StaticShapeData(SwolfLogo) +{ + className = Logo; + shapeFile = "teamlogo_sw.dts"; + alwaysAmbient = true; +}; + +datablock StaticShapeData(LogoProjector) +{ + className = Projector; + catagory = "Objectives"; + shapeFile = "teamlogo_projector.dts"; + alwaysAmbient = true; + isInvincible = true; +}; + +function Projector::onAdd(%data, %obj) +{ + Parent::onAdd(%data, %obj); + %obj.holo = 0; +} + +//////////////////////////////////////////// +// Tapestries +/////////////////////////////////////////// +datablock StaticShapeData(Banner_Honor) +{ + catagory = "Eyecandy"; + shapefile = "banner_honor.dts"; +}; + +datablock StaticShapeData(Banner_Strength) +{ + catagory = "Eyecandy"; + shapefile = "banner_strength.dts"; +}; + +datablock StaticShapeData(Banner_Unity) +{ + catagory = "Eyecandy"; + shapefile = "banner_unity.dts"; +}; + +//////////////////////////////////////////////////////////////////////////////// +// + +//-------------------------------------------------------------------------- +// Totally static objects +// The format of these strings are: +// 0: Catagory +// 1: Name +// 2: File +// 3: MaxSlope [ only used with the randomOrg function ] +// 4: ZOffset [ only used with the randomOrg function ] +// 5: slopeWithTerrain [ only used with the randomOrg function ] +// 6: minScale [ only used with the randomOrg function ] +// 7: maxScale [ only used with the randomOrg function ] + + +$StaticTSObjects[0] = "Organics BiodermPlant3 xorg3.dts"; +$StaticTSObjects[1] = "Organics BiodermPlant4 xorg4.dts"; +$StaticTSObjects[2] = "Organics BiodermPlant5 xorg5.dts"; +$StaticTSObjects[3] = "Organics BiodermPlant20 xorg20.dts"; +$StaticTSObjects[4] = "Organics BiodermPlant21 xorg21.dts"; +$StaticTSObjects[5] = "Organics BiodermPlant22 xorg22.dts"; + +$StaticTSObjects[6] = "Organics BEPlant1 borg1.dts 40 0.35 1 0.5 2"; +$StaticTSObjects[7] = "Organics BEPlant5 borg5.dts 40 0.0 1 1 1.5"; +$StaticTSObjects[8] = "Organics BEPlant6 borg6.dts"; +$StaticTSObjects[9] = "Organics BEPlant7 borg7.dts"; + +$StaticTSObjects[10] = "Organics BEPlant12 borg12.dts"; +$StaticTSObjects[11] = "Organics BEPlant13 borg13.dts"; +$StaticTSObjects[12] = "Organics BELgTree16 borg16.dts 20 -3.0 0 0.8 1.5"; +$StaticTSObjects[13] = "Organics BESmTree17 borg17.dts 20 -3.0 1 0.8 1.5"; +$StaticTSObjects[14] = "Organics BELgTree18 borg18.dts 20 -3.0 0 0.8 1.5"; +$StaticTSObjects[15] = "Organics BELgTree19 borg19.dts 20 -3.0 0 0.8 1.5"; +$StaticTSObjects[16] = "Organics BEPlant20 borg20.dts"; + +$StaticTSObjects[17] = "Organics BEPlant23 borg23.dts"; +$StaticTSObjects[18] = "Organics BEPlant25 borg25.dts"; + +$StaticTSObjects[19] = "Organics BEPlant31 borg31.dts"; +$StaticTSObjects[20] = "Organics BEPlant32 borg32.dts"; +$StaticTSObjects[21] = "Organics BEPlant33 borg33.dts"; +$StaticTSObjects[22] = "Organics BEPlant34 borg34.dts"; + +$StaticTSObjects[23] = "Organics PhoenixPlant1 porg1.dts"; +$StaticTSObjects[24] = "Organics PhoenixPlant2 porg2.dts"; +$StaticTSObjects[25] = "Organics PhoenixPlant3 porg3.dts"; +$StaticTSObjects[26] = "Organics PhoenixPlant5 porg5.dts 25 -0.2 1 0.6 1.0"; +$StaticTSObjects[27] = "Organics PhoenixPlant6 porg6.dts"; +$StaticTSObjects[28] = "Organics PhoenixPlant20 porg20.dts"; + +$StaticTSObjects[29] = "Organics PhoenixPlant22 porg22.dts 25 0.1 1 0.8 1.4"; +$StaticTSObjects[30] = "Organics SWTree20 sorg20.dts"; +$StaticTSObjects[31] = "Organics SWShrub21 sorg21.dts"; +$StaticTSObjects[32] = "Organics SWTree22 sorg22.dts"; +$StaticTSObjects[33] = "Organics SWShrub23 sorg23.dts"; +$StaticTSObjects[34] = "Organics SWShrub24 sorg24.dts"; +$StaticTSObjects[35] = "Stackables Crate1 stackable1l.dts"; +$StaticTSObjects[36] = "Stackables Crate2 stackable1m.dts"; +$StaticTSObjects[37] = "Stackables Crate3 stackable1s.dts"; +$StaticTSObjects[38] = "Stackables Crate4 stackable2l.dts"; +$StaticTSObjects[39] = "Stackables Crate5 stackable2m.dts"; +$StaticTSObjects[40] = "Stackables Crate6 stackable2s.dts"; +$StaticTSObjects[41] = "Stackables Crate7 stackable3l.dts"; +$StaticTSObjects[42] = "Stackables Crate8 stackable3m.dts"; +$StaticTSObjects[43] = "Stackables Crate9 stackable3s.dts"; +$StaticTSObjects[44] = "Stackables Crate10 stackable4l.dts"; +$StaticTSObjects[45] = "Stackables Crate11 stackable4m.dts"; +$StaticTSObjects[46] = "Stackables Crate12 stackable5l.dts"; +$StaticTSObjects[47] = "Debris ScoutWreckageShape vehicle_air_scout_wreck.dts"; +$StaticTSObjects[48] = "Debris TankWreckageShape vehicle_land_assault_wreck.dts"; +$StaticTSObjects[49] = "Organics DSPlant16 dorg16.dts 20 -3.0 0 0.8 1.5"; +$StaticTSObjects[50] = "Organics DSPlant17 dorg17.dts 20 -3.0 1 0.8 1.5"; +$StaticTSObjects[51] = "Organics DSPlant18 dorg18.dts 20 -3.0 0 0.8 1.5"; +$StaticTSObjects[52] = "Organics DSPlant19 dorg19.dts 20 -3.0 0 0.8 1.5"; + +$StaticTSObjects[53] = "PlayerArmors LightMaleHumanArmorImage light_male.dts"; +$StaticTSObjects[54] = "PlayerArmors MediumMaleHumanArmorImage medium_male.dts"; +$StaticTSObjects[55] = "PlayerArmors HeavyMaleHumanArmorImage heavy_male.dts"; +$StaticTSObjects[56] = "PlayerArmors LightFemaleHumanArmorImage light_female.dts"; +$StaticTSObjects[57] = "PlayerArmors MediumFemaleHumanArmorImage medium_female.dts"; +$StaticTSObjects[58] = "PlayerArmors HeavyFemaleHumanArmorImage heavy_male.dts"; +$StaticTSObjects[59] = "PlayerArmors LightMaleBiodermArmorImage bioderm_light.dts"; +$StaticTSObjects[60] = "PlayerArmors MediumMaleBiodermArmorImage bioderm_medium.dts"; +$StaticTSObjects[61] = "PlayerArmors HeavyMaleBiodermArmorImage bioderm_heavy.dts"; + +$StaticTSObjects[62] = "Organics BEGrass1 Borg6.dts"; + +$StaticTSObjects[63] = "Plugs bePlug bmiscf.dts"; +$StaticTSObjects[64] = "Plugs dsPlug dmiscf.dts"; +$StaticTSObjects[65] = "Plugs xPlug xmiscf.dts"; +$StaticTSObjects[66] = "Plugs hPlug pmiscf.dts"; +$StaticTSObjects[67] = "Plugs swPlug smiscf.dts"; + +$StaticTSObjects[68] = "Statues Base statue_base.dts"; +$StaticTSObjects[69] = "Statues HeavyMaleStatue statue_hmale.dts"; +$StaticTSObjects[70] = "Statues LightFemaleStatue statue_lfemale.dts"; +$StaticTSObjects[71] = "Statues LightMaleStatue statue_lmale.dts"; +$StaticTSObjects[72] = "Statues Plaque statue_plaque.dts"; + +$StaticTSObjects[73] = "Debris BomberDebris1 bdb1.dts"; +$StaticTSObjects[74] = "Debris BomberDebris2 bdb2.dts"; +$StaticTSObjects[75] = "Debris BomberDebris3 bdb3.dts"; +$StaticTSObjects[76] = "Debris BomberDebris4 bdb4.dts"; +$StaticTSObjects[77] = "Debris BomberDebris5 bdb5.dts"; +$StaticTSObjects[78] = "Debris HavocDebris1 hdb1.dts"; +$StaticTSObjects[79] = "Debris HavocDebris2 hdb2.dts"; +$StaticTSObjects[80] = "Debris HavocDebris3 hdb3.dts"; +$StaticTSObjects[81] = "Debris IDebris1 idb.dts"; +$StaticTSObjects[82] = "Debris MPBDebris1 mpbdb1.dts"; +$StaticTSObjects[83] = "Debris MPBDebris2 mpbdb2.dts"; +$StaticTSObjects[84] = "Debris MPBDebris3 mpbdb3.dts"; +$StaticTSObjects[85] = "Debris MPBDebris4 mpbdb4.dts"; +$StaticTSObjects[86] = "Debris ScoutDebris1 sdb1.dts"; +$StaticTSObjects[87] = "Debris TankDebris1 tdb1.dts"; +$StaticTSObjects[88] = "Debris TankDebris2 tdb2.dts"; +$StaticTSObjects[89] = "Debris TankDebris3 tdb3.dts"; +$StaticTSObjects[90] = "Debris GraveMarker1 gravemarker1.dts"; +$StaticTSObjects[91] = "Test Test1 test1.dts"; +$StaticTSObjects[92] = "Test Test2 test2.dts"; +$StaticTSObjects[93] = "Test Test3 test3.dts"; +$StaticTSObjects[94] = "Test Test4 test4.dts"; +$StaticTSObjects[95] = "Test Test5 test5.dts"; + + + +$NumStaticTSObjects = 96; + +function TSStatic::create(%shapeName) +{ + //echo("Foo:" SPC %shapeName); + %obj = new TSStatic() + { + shapeName = %shapeName; + }; + return(%obj); +} + +function TSStatic::damage(%this) +{ + // prevent console error spam +} + +function stripFields(%this) +{ + if(%this $= "") + %this = MissionGroup; + for (%i = 0; %i < %this.getCount(); %i++){ + %obj = %this.getObject(%i); + if (%obj.getClassName() $= SimGroup) + { + %obj.powerCount = ""; + %obj.team = ""; + stripFields(%obj); + } + else + { + %obj.threshold = ""; + %obj.team = ""; + %obj.powerCount = ""; + %obj.trigger = ""; + %obj.hidden = ""; + %obj.locked = "true"; + %obj.notReady = ""; + %obj.inUse = ""; + %obj.triggeredBy = ""; + %obj.lastDamagedBy = ""; + %obj.lastDamagedByTeam =""; + %obj.isHome = ""; + %obj.originalPosition = ""; + %obj.objectiveCompleted = ""; + %obj.number = ""; + %obj.target = ""; + %obj.lockCount = ""; + %obj.homingCount = ""; + %obj.projector = ""; + %obj.holo = ""; + %obj.waypoint = ""; + %obj.scoreValue =""; + %obj.damageTimeMS = ""; + %obj.station = ""; + %homingCount = ""; + } + } +} diff --git a/scripts/station.cs b/scripts/station.cs new file mode 100644 index 0000000..1de7f4c --- /dev/null +++ b/scripts/station.cs @@ -0,0 +1,1283 @@ +//****************************************************************************** +//* Station - Data Blocks * +//****************************************************************************** +datablock EffectProfile(StationInventoryActivateEffect) +{ + effectname = "powered/inv_pad_on"; + minDistance = 5.0; + maxDistance = 7.5; +}; + +datablock EffectProfile(StationVehicleAcitvateEffect) +{ + effectname = "powered/vehicle_screen_on2"; + minDistance = 3.0; + maxDistance = 5.0; +}; + +datablock EffectProfile(StationVehicleDeactivateEffect) +{ + effectname = "powered/vehicle_screen_off"; + minDistance = 3.0; + maxDistance = 5.0; +}; + +//datablock EffectProfile(MobileBaseInventoryActivateEffect) +//{ +// effectname = "misc/diagnostic_on"; +// minDistance = 3.0; +//}; + +datablock EffectProfile(StationAccessDeniedEffect) +{ + effectname = "powered/station_denied"; + minDistance = 3.0; + maxDistance = 5.0; +}; + +datablock AudioProfile(StationInventoryActivateSound) +{ + filename = "fx/powered/inv_pad_on.wav"; + description = AudioClose3d; + preload = true; + effect = StationInventoryActivateEffect; +}; + +datablock AudioProfile(MobileBaseInventoryActivateSound) +{ + filename = "fx/vehicles/mpb_inv_station.wav"; + description = AudioClose3d; + preload = true; + effect = StationInventoryActivateEffect; +}; + +datablock AudioProfile(DepInvActivateSound) +{ + filename = "fx/powered/dep_inv_station.wav"; + description = AudioClose3d; + preload = true; + effect = StationInventoryActivateEffect; +}; + +datablock AudioProfile(StationVehicleAcitvateSound) +{ + filename = "fx/powered/vehicle_screen_on2.wav"; + description = AudioClosest3d; + preload = true; + effect = StationVehicleAcitvateEffect; +}; + +datablock AudioProfile(StationVehicleDeactivateSound) +{ + filename = "fx/powered/vehicle_screen_off.wav"; + description = AudioClose3d; + preload = true; + effect = StationVehicleDeactivateEffect; +}; + +datablock AudioProfile(StationAccessDeniedSound) +{ + filename = "fx/powered/station_denied.wav"; + description = AudioClosest3d; + preload = true; + effect = StationAccessDeniedEffect; +}; + +datablock AudioProfile(StationVehicleHumSound) +{ + filename = "fx/powered/station_hum.wav"; + description = CloseLooping3d; + preload = true; +}; + +datablock AudioProfile(StationInventoryHumSound) +{ + filename = "fx/powered/station_hum.wav"; + description = CloseLooping3d; + preload = true; +}; + +datablock StationFXPersonalData( PersonalInvFX ) +{ + delay = 0; + fadeDelay = 0.5; + lifetime = 1.2; + height = 2.5; + numArcSegments = 10.0; + numDegrees = 180.0; + trailFadeTime = 0.5; + leftRadius = 1.85; + rightRadius = 1.85; + leftNodeName = "FX1"; + rightNodeName = "FX2"; + + texture[0] = "special/stationLight"; +}; + + +datablock DebrisData( StationDebris ) +{ + explodeOnMaxBounce = false; + + elasticity = 0.40; + friction = 0.5; + + lifetime = 17.0; + lifetimeVariance = 0.0; + + minSpinSpeed = 60; + maxSpinSpeed = 600; + + numBounces = 10; + bounceVariance = 0; + + staticOnMaxBounce = true; + + useRadiusMass = true; + baseRadius = 0.4; + + velocity = 9.0; + velocityVariance = 4.5; + +}; + +datablock StaticShapeData(StationInventory) : StaticShapeDamageProfile +{ + className = Station; + catagory = "Stations"; + shapeFile = "station_inv_human.dts"; + maxDamage = 1.00; + destroyedLevel = 1.00; + disabledLevel = 0.70; + explosion = ShapeExplosion; + expDmgRadius = 8.0; + expDamage = 0.4; + expImpulse = 1500.0; + // don't allow this object to be damaged in non-team-based + // mission types (DM, Rabbit, Bounty, Hunters) + noIndividualDamage = true; + + dynamicType = $TypeMasks::StationObjectType; + isShielded = true; + energyPerDamagePoint = 75; + maxEnergy = 50; + rechargeRate = 0.35; + doesRepair = true; + humSound = StationInventoryHumSound; + + cmdCategory = "Support"; + cmdIcon = CMDStationIcon; + cmdMiniIconName = "commander/MiniIcons/com_inventory_grey"; + targetNameTag = 'Inventory'; + targetTypeTag = 'Station'; + + debrisShapeName = "debris_generic.dts"; + debris = StationDebris; + needsPower = true; +}; + +datablock StaticShapeData(StationAmmo) : StaticShapeDamageProfile +{ + className = Station; + catagory = "Stations"; +// shapeFile = "station_ammo.dts"; + shapeFile = "station_inv_human.dts"; + maxDamage = 1.00; + destroyedLevel = 1.00; + disabledLevel = 0.70; + explosion = ShapeExplosion; + expDmgRadius = 8.0; + expDamage = 0.4; + expImpulse = 1500.0; + // don't allow this object to be damaged in non-team-based + // mission types (DM, Rabbit, Bounty, Hunters) + noIndividualDamage = true; + + dynamicType = $TypeMasks::StationObjectType; + isShielded = true; + energyPerDamagePoint = 75; + maxEnergy = 50; + rechargeRate = 0.35; + doesRepair = true; + humSound = StationInventoryHumSound; + + cmdCategory = "Support"; + cmdIcon = CMDStationIcon; + cmdMiniIconName = "commander/MiniIcons/com_inventory_grey"; + targetNameTag = 'Ammo'; + targetTypeTag = 'Station'; + + debrisShapeName = "debris_generic.dts"; + debris = StationDebris; +}; + +datablock StaticShapeData(StationVehicle) : StaticShapeDamageProfile +{ +//[[CHANGE]] Added some observer information.. + className = Station; + catagory = "Stations"; + shapeFile = "vehicle_pad_station.dts"; + maxDamage = 1.20; + destroyedLevel = 1.20; + disabledLevel = 0.84; + explosion = ShapeExplosion; + canControl = true; + expDmgRadius = 10.0; + expDamage = 0.4; + expImpulse = 1500.0; + dynamicType = $TypeMasks::StationObjectType; + isShielded = true; + energyPerDamagePoint = 33; + maxEnergy = 250; + rechargeRate = 0.31; + humSound = StationVehicleHumSound; + // don't let these be damaged in Siege missions + noDamageInSiege = true; + cmdCategory = "Support"; + cmdIcon = CMDVehicleStationIcon; + cmdMiniIconName = "commander/MiniIcons/com_vehicle_pad_inventory"; + targetTypeTag = 'Vehicle Station'; + observeParameters = "0 10.0 10.0"; + + debrisShapeName = "debris_generic.dts"; + debris = StationDebris; + + minLookAngle = -1.5; + maxLookAngle = 1.5; + maxFreelookAngle = 3.0; + + cameraMaxDist = 40; + cameraOffset = 20; + cameraLag = 1.5; + noIndividualDamage = true; +}; + +datablock StaticShapeData(StationVehiclePad) +{ + className = Station; + catagory = "Stations"; + shapeFile = "vehicle_pad.dts"; + isInvincible = true; + dynamicType = $TypeMasks::StaticObjectType; + rechargeRate = 0.05; + + // ------------------------------------------ + // z0dd - ZOD, 5/8/02. CC bug fix parameter. + // Part of overall V-Station creation change. + targetTypeTag = 'Vehicle Pad'; +}; + +//datablock StaticShapeData(StationAmmo) +//{ +// className = Station; +// catagory = "Stations"; +// shapeFile = "station_ammo.dts"; +// maxDamage = 1.0; +// disabledLevel = 0.6; +// destroyedLevel = 0.8; +// icon = "CMDStationIcon"; +// dynamicType = $TypeMasks::StationObjectType; +//}; + +datablock StaticShapeData(MobileInvStation) +{ + className = Station; + catagory = "Stations"; + shapeFile = "station_inv_mpb.dts"; + icon = "CMDStationIcon"; + // don't allow this object to be damaged in non-team-based + // mission types (DM, Rabbit, Bounty, Hunters) + noIndividualDamage = true; + + dynamicType = $TypeMasks::StationObjectType; + rechargeRate = 0.256; + doesRepair = true; +}; + + +//****************************************************************************** +//* Station - Functions * +//****************************************************************************** + +//////////////////////////////////////////////////////////////////////////////// +/// -Inventory- //////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + +/// -Inventory- //////////////////////////////////////////////////////////////// +//Function -- onAdd (%this, %obj) +// %this = Object data block +// %obj = Object being added +//Decription -- Called when the object is added to the mission +//////////////////////////////////////////////////////////////////////////////// +function StationInventory::onAdd(%this, %obj) +{ + Parent::onAdd(%this, %obj); + + %obj.setRechargeRate(%obj.getDatablock().rechargeRate); + %trigger = new Trigger() + { + dataBlock = stationTrigger; + polyhedron = "-0.75 0.75 0.1 1.5 0.0 0.0 0.0 -1.5 0.0 0.0 0.0 2.3"; + }; + MissionCleanup.add(%trigger); + %trigger.setTransform(%obj.getTransform()); + + %trigger.station = %obj; + %trigger.mainObj = %obj; + %trigger.disableObj = %obj; + %obj.trigger = %trigger; +} + +/// -Inventory- //////////////////////////////////////////////////////////////// +//Function -- stationReady(%data, %obj) +// %data = Station Data Block +// %obj = Station Object +//Decription -- Called when station has been triggered and animation is +// completed +//////////////////////////////////////////////////////////////////////////////// +function StationInventory::stationReady(%data, %obj) +{ + //Display the Inventory Station GUI here + %obj.notReady = 1; + %obj.inUse = "Down"; + %obj.schedule(500,"playThread",$ActivateThread,"activate1"); + %player = %obj.triggeredBy; + %energy = %player.getEnergyLevel(); + // ------------------------------------------------- + // z0dd - ZOD, 4/20/02. Addition. Inv energy bug fix + %max = %player.getDatablock().maxEnergy; + + %player.setCloaked(true); + %player.schedule(500, "setCloaked", false); + if (!%player.client.isAIControlled()) + buyFavorites(%player.client); + + // ------------------------------------------------- + // z0dd - ZOD, 4/20/02. Addition. Inv energy bug fix + //%player.setEnergyLevel(%energy); + %player.setEnergyLevel(mFloor(%player.getDatablock().maxEnergy * %energy / %max)); + + %data.schedule( 500, "beginPersonalInvEffect", %obj ); +} + +function StationInventory::beginPersonalInvEffect( %data, %obj ) +{ + if (!%obj.isDisabled()) + { + %fx = new StationFXPersonal() + { + dataBlock = PersonalInvFX; + stationObject = %obj; + }; + } +} + +/// -Inventory- //////////////////////////////////////////////////////////////// +//Function -- stationFinished(%data, %obj) +// %data = Station Data Block +// %obj = Station Object +//Decription -- Called when player has left the station +//////////////////////////////////////////////////////////////////////////////// +function StationInventory::stationFinished(%data, %obj) +{ + //Hide the Inventory Station GUI +} + +/// -Inventory- //////////////////////////////////////////////////////////////// +//Function -- getSound(%data, %forward) +// %data = Station Data Block +// %forward = direction the animation is playing +//Decription -- This sound will be played at the same time as the activate +// animation. +//////////////////////////////////////////////////////////////////////////////// +function StationInventory::getSound(%data, %forward) +{ + if(%forward) + return "StationInventoryActivateSound"; + else + return false; +} + +/// -Inventory- //////////////////////////////////////////////////////////////// +//Function -- setPlayerPosition(%data, %obj, %trigger, %colObj) +// %data = Station Data Block +// %obj = Station Object +// %trigger = Stations trigger +// %colObj = Object that is at the station +//Decription -- Called when player enters the trigger. Used to set the player +// in the center of the station. +//////////////////////////////////////////////////////////////////////////////// +function StationInventory::setPlayersPosition(%data, %obj, %trigger, %colObj) +{ + %vel = getWords(%colObj.getVelocity(), 0, 1) @ " 0"; + if((VectorLen(%vel) < 22) && (%obj.triggeredBy != %colObj)) + { + %pos = %trigger.position; + %colObj.setvelocity("0 0 0"); + %rot = getWords(%colObj.getTransform(),3, 6); + %pos = getWord(%pos,0) @ " " @ getWord(%pos,1) @ " " @ getWord(%pos,2) + 0.8; + %terrain = getTerrainHeight2(%pos); + if (!(getWord(%pos,2) < getWord(%terrain,2) || %terrain $= "") || $Host::AllowUnderground) + //%colObj.setTransform(%pos @ " " @ %rot);//center player on object + return true; + } + return false; +} + +/////////////////////////////////////////////////////////////////////////////// +/// -Ammo- //////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +function StationAmmo::onAdd(%this, %obj) +{ + Parent::onAdd(%this, %obj); + + %obj.setRechargeRate(%obj.getDatablock().rechargeRate); + %trigger = new Trigger() + { + dataBlock = stationTrigger; + polyhedron = "-0.75 0.75 0.1 1.5 0.0 0.0 0.0 -1.5 0.0 0.0 0.0 2.3"; + }; + MissionCleanup.add(%trigger); + %trigger.setTransform(%obj.getTransform()); + + %trigger.station = %obj; + %trigger.mainObj = %obj; + %trigger.disableObj = %obj; + %obj.trigger = %trigger; +} + +//------------------------------------------------------------------------------- +function StationAmmo::stationReady(%data, %obj) +{ + //error("StationAmmo::stationReady"); + %obj.notReady = 1; + %obj.inUse = "Down"; + %obj.setThreadDir($ActivateThread, true); + %obj.schedule(100, "playThread", $ActivateThread, "activate1"); + %player = %obj.triggeredBy; + %energy = %player.getEnergyLevel(); + //%player.setCloaked(true); + //%player.schedule(500, "setCloaked", false); + + + if (!%player.client.isAIControlled()) + getAmmoStationLovin(%player.client); + //%data.schedule( 500, "beginPersonalInvEffect", %obj ); +} + +//------------------------------------------------------------------------------- +function StationAmmo::onEndSequence(%data, %obj, %thread) +{ + if(%thread == $ActivateThread) + { + %obj.setThreadDir($ActivateThread, false); + %obj.playThread( $ActivateThread, "activate1"); + if(%obj.inUse $= "Up") + { + %data.stationReady(%obj); + %player = %obj.triggeredBy; + if(%data.doesRepair && !%player.stationRepairing && %player.getDamageLevel() != 0) { + %oldRate = %player.getRepairRate(); + %player.setRepairRate(%oldRate + 0.00625); + %player.stationRepairing = 1; + } + } + } + //Parent::onEndSequence(%data, %obj, %thread); +} + +//------------------------------------------------------------------------------- +function StationAmmo::stationFinished(%data, %obj) +{ + //Hide the Inventory Station GUI +} + +//------------------------------------------------------------------------------- +function StationAmmo::getSound(%data, %forward) +{ + if(%forward) + return "StationInventoryActivateSound"; + else + return false; +} + +//------------------------------------------------------------------------------- +function StationAmmo::setPlayersPosition(%data, %obj, %trigger, %colObj) +{ + %vel = getWords(%colObj.getVelocity(), 0, 1) @ " 0"; + if((VectorLen(%vel) < 22) && (%obj.triggeredBy != %colObj)) + { + %pos = %trigger.position; + %colObj.setvelocity("0 0 0"); + %rot = getWords(%colObj.getTransform(),3, 6); + %pos = getWord(%pos,0) @ " " @ getWord(%pos,1) @ " " @ getWord(%pos,2) + 0.8; + %terrain = getTerrainHeight2(%pos); + if (!(getWord(%pos,2) < getWord(%terrain,2) || %terrain $= "") || $Host::AllowUnderground) + //%colObj.setTransform(%pos @ " " @ %rot);//center player on object + return true; + } + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +/// -Vehicle- ////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + +/// -Vehicle- ////////////////////////////////////////////////////////////////// +//Function -- onAdd (%this, %obj) +// %this = Object data block +// %obj = Object being added +//Decription -- Called when the object is added to the mission +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// z0dd - ZOD - Founder(founder@mechina.com), 5/8/02. Totall re-write of Vehicle +// station creation. More stable, addresses some power related bugs. + +// Do not need this anymore. +//function StationVehicle::onAdd(%this, %obj) +//{ +// Parent::onAdd(%this, %obj); + +// %obj.setRechargeRate(%obj.getDatablock().rechargeRate); +// %trigger = new Trigger() +// { +// dataBlock = stationTrigger; +// polyhedron = "-0.75 0.75 0.0 1.5 0.0 0.0 0.0 -1.5 0.0 0.0 0.0 2.0"; +// }; +// MissionCleanup.add(%trigger); +// %trigger.setTransform(%obj.getTransform()); +// %trigger.station = %obj; +// %obj.trigger = %trigger; +//} + +// This now creates the vehicle station trigger. +function StationVehicle::createTrigger(%this, %obj) +{ + %trigger = new Trigger() + { + dataBlock = stationTrigger; + polyhedron = "-0.75 0.75 0.0 1.5 0.0 0.0 0.0 -1.5 0.0 0.0 0.0 2.0"; + }; + MissionCleanup.add(%trigger); + %trigger.setTransform(%obj.getTransform()); + %trigger.station = %obj; + %obj.trigger = %trigger; +} +// End z0dd - ZOD - Founder +// ----------------------------------------------------------------------------- + +/// -Vehicle- ////////////////////////////////////////////////////////////////// +//Function -- stationReady(%data, %obj) +// %data = Station Data Block +// %obj = Station Object +//Decription -- Called when station has been triggered and animation is +// completed +//////////////////////////////////////////////////////////////////////////////// +function StationVehicle::stationReady(%data, %obj) +{ + // Make sure none of the other popup huds are active: + messageClient( %obj.triggeredBy.client, 'CloseHud', "", 'scoreScreen' ); + messageClient( %obj.triggeredBy.client, 'CloseHud', "", 'inventoryScreen' ); + + //[[CHANGE]] Make sure the player teleports... + %obj.triggeredby.client.telebuy = ""; + + //Display the Vehicle Station GUI + commandToClient(%obj.triggeredBy.client, 'StationVehicleShowHud'); +} + +/// -Vehicle- ////////////////////////////////////////////////////////////////// +//Function -- stationFinished(%data, %obj) +// %data = Station Data Block +// %obj = Station Object +//Decription -- Called when player has left the station +//////////////////////////////////////////////////////////////////////////////// +function StationVehicle::stationFinished(%data, %obj) +{ + //Hide the Vehicle Station GUI + if(!%obj.triggeredBy.isMounted()) + commandToClient(%obj.triggeredBy.client, 'StationVehicleHideHud'); + else + commandToClient(%obj.triggeredBy.client, 'StationVehicleHideJustHud'); + +} + +/// -Vehicle- ////////////////////////////////////////////////////////////////// +//Function -- getSound(%data, %forward) +// %data = Station Data Block +// %forward = direction the animation is playing +//Decription -- This sound will be played at the same time as the activate +// animation. +//////////////////////////////////////////////////////////////////////////////// +function StationVehicle::getSound(%data, %forward) +{ + if(%forward) + return "StationVehicleAcitvateSound"; + else + return "StationVehicleDeactivateSound"; +} + +/// -Vehicle- ////////////////////////////////////////////////////////////////// +//Function -- setPlayerPosition(%data, %obj, %trigger, %colObj) +// %data = Station Data Block +// %obj = Station Object +// %trigger = Stations trigger +// %colObj = Object that is at the station +//Decription -- Called when player enters the trigger. Used to set the player +// in the center of the station. +//////////////////////////////////////////////////////////////////////////////// +function StationVehicle::setPlayersPosition(%data, %obj, %trigger, %colObj) +{ + %vel = getWords(%colObj.getVelocity(), 0, 1) @ " 0"; + if((VectorLen(%vel) < 22) && (%obj.triggeredBy != %colObj)) + { + %posXY = getWords(%trigger.getTransform(),0 ,1); + %posZ = getWord(%trigger.getTransform(), 2); + %rotZ = getWord(%obj.getTransform(), 5); + %angle = getWord(%obj.getTransform(), 6); + %angle += 3.141592654; + if(%angle > 6.283185308) + %angle = %angle - 6.283185308; + %colObj.setvelocity("0 0 0"); + %pos = %posXY @ " " @ %posZ + 0.2; + %terrain = getTerrainHeight2(%pos); + if (!(getWord(%pos,2) < getWord(%terrain,2) || %terrain $= "") || $Host::AllowUnderground) + %colObj.setTransform(%pos @ " " @ "0 0 " @ %rotZ @ " " @ %angle );//center player on object + return true; + } + return false; +} +// ----------------------------------------------------------------------------- +// z0dd - ZOD - Founder(founder@mechina.com), 5/8/02. Totall re-write of Vehicle +// station creation. More stable, addresses some power related bugs. + +function StationVehiclePad::onAdd(%this, %obj) +{ + Parent::onAdd(%this, %obj); + + %obj.ready = true; + %obj.setRechargeRate(%obj.getDatablock().rechargeRate); + + //------------------------------------------------------------- + // All of this moved to StationVehiclePad::createStationVehicle + //%xform = %obj.getSlotTransform(0); + //%pos = getWords(%xform, 0, 2); + //%rot = getWords(%xform, 3, 5); + //%angle = (getWord(%xform, 6) * 180) / 3.14159; + + //%sv = new StaticShape() { + // scale = "1 1 1"; + // dataBlock = StationVehicle; + // lockCount = "0"; + // homingCount = "0"; + // team = %obj.team; + // position = %pos; + // rotation = %rot @ " " @ %angle; + //}; + + //MissionCleanup.add(%sv); + //%sv.getDataBlock().gainPower(%sv); + //%sv.pad = %obj; + //%obj.station = %sv; + //%sv.trigger.mainObj = %obj; + //%sv.trigger.disableObj = %sv; + + //Remove unwanted vehicles + //if(%obj.scoutVehicle !$= "Removed") + // %sv.vehicle[scoutvehicle] = true; + //if(%obj.assaultVehicle !$= "Removed") + // %sv.vehicle[assaultVehicle] = true; + //if(%obj.mobileBaseVehicle !$= "Removed") + //{ + // %sv.vehicle[mobileBasevehicle] = true; + //} + //if(%obj.scoutFlyer !$= "Removed") + // %sv.vehicle[scoutFlyer] = true; + //if(%obj.bomberFlyer !$= "Removed") + // %sv.vehicle[bomberFlyer] = true; + //if(%obj.hapcFlyer !$= "Removed") + // %sv.vehicle[hapcFlyer] = true; + + // z0dd - ZOD - Founder. Schedule the vehicle station creation. + // Don't create the station if the pad is hidden by the current mission type. + //error("CURRENT MISSION TYPE: " @ $CurrentMissionType @ ", ALLOWED TYPE: " @ %obj.missionTypesList); + if($CurrentMissionType $= %obj.missionTypesList || %obj.missionTypesList $="") + %this.schedule(0, "createStationVehicle", %obj); +} + +function StationVehiclePad::createStationVehicle(%data, %obj) +{ + // This code used to be called from StationVehiclePad::onAdd + // This was changed so we can add the station to the mission group + // so it gets powered properly and auto cleaned up at mission end. + + // Get the v-pads mission group so we can place the station in it. + %group = %obj.getGroup(); + + // Set the default transform based on the vehicle pads slot + %xform = %obj.getSlotTransform(0); + %position = getWords(%xform, 0, 2); + %rotation = getWords(%xform, 3, 5); + %angle = (getWord(%xform, 6) * 180) / 3.14159; + + // Place these parameter's in the v-pad datablock located in mis file. + // If the mapper doesn't move the station, use the default location. + if(%obj.stationPos $= "" || %obj.stationRot $= "") + { + %pos = %position; + %rot = %rotation @ " " @ %angle; + } + else + { + %pos = %obj.stationPos; + %rot = %obj.stationRot; + } + + %sv = new StaticShape() { + scale = "1 1 1"; + dataBlock = "StationVehicle"; + lockCount = "0"; + homingCount = "0"; + team = %obj.team; + position = %pos; + rotation = %rot; + }; + + // Add the station to the v-pads mission group for cleanup and power. + %group.add(%sv); + %sv.setPersistent(false); // set the station to not save. + + // Apparently called to early on mission load done, call it now. + %sv.getDataBlock().gainPower(%sv); + + // Create the trigger + %sv.getDataBlock().createTrigger(%sv); + %sv.pad = %obj; + %obj.station = %sv; + %sv.trigger.mainObj = %obj; + %sv.trigger.disableObj = %sv; + + // Set the sensor group. + if(%sv.getTarget() != -1) + setTargetSensorGroup(%sv.getTarget(), %obj.team); + + //Remove unwanted vehicles + if(%obj.scoutVehicle !$= "Removed") + %sv.vehicle[scoutvehicle] = true; + if(%obj.SuperScoutVehicle !$= "Removed") + %sv.vehicle[SuperScoutVehicle] = true; + if(%obj.assaultVehicle !$= "Removed") + %sv.vehicle[assaultVehicle] = true; + if(%obj.mobileBaseVehicle !$= "Removed") + %sv.vehicle[mobileBasevehicle] = true; + if(%obj.scoutFlyer !$= "Removed") + %sv.vehicle[scoutFlyer] = true; + if(%obj.bomberFlyer !$= "Removed") + %sv.vehicle[bomberFlyer] = true; + if(%obj.hapcFlyer !$= "Removed") + %sv.vehicle[hapcFlyer] = true; + if(%obj.SuperHAPCFlyer !$= "Removed") + %sv.vehicle[SuperHAPCFlyer] = true; + if(%obj.Artillery !$= "Removed") + %sv.vehicle[Artillery] = true; +} +// End z0dd - ZOD - Founder +// ----------------------------------------------------------------------------- + +function StationVehiclePad::onEndSequence(%data, %obj, %thread) +{ + if(%thread == $ActivateThread) + { + %obj.ready = true; + %obj.stopThread($ActivateThread); + } + Parent::onEndSequence(%data, %obj, %thread); +} + +//////////////////////////////////////////////////////////////////////////////// +/// -Mobile Base Inventory- //////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + +/// -Mobile Base- ////////////////////////////////////////////////////////////// +//Function -- onAdd (%this, %obj) +// %this = Object data block +// %obj = Object being added +//Decription -- Called when the object is added to the mission +//////////////////////////////////////////////////////////////////////////////// +function MobileInvStation::onAdd(%this, %obj) +{ +} + +function MobileInvStation::createTrigger(%this, %obj) +{ + Parent::onAdd(%this, %obj); + + %obj.setRechargeRate(%obj.getDatablock().rechargeRate); + %trigger = new Trigger() + { + dataBlock = stationTrigger; + polyhedron = "-0.75 0.75 0.1 1.5 0.0 0.0 0.0 -1.5 0.0 0.0 0.0 2.3"; + }; + MissionCleanup.add(%trigger); + %trigger.setTransform(%obj.vehicle.getSlotTransform(2)); + + %trigger.station = %obj; + %trigger.mainObj = %obj; + %trigger.disableObj = %obj; + + %obj.trigger = %trigger; +// createTarget(%obj, 'Inventory Station', "", "", 'Station', 0, 0); +} + +/// -Mobile Base- ////////////////////////////////////////////////////////////// +//Function -- stationReady(%data, %obj) +// %data = Station Data Block +// %obj = Station Object +//Decription -- Called when station has been triggered and animation is +// completed +//////////////////////////////////////////////////////////////////////////////// +function MobileInvStation::stationReady(%data, %obj) +{ + //Display the Inventory Station GUI here + %obj.notReady = 1; + %obj.inUse = "Down"; + %obj.schedule(200,"playThread",$ActivateThread,"activate1"); + %obj.getObjectMount().playThread($ActivateThread,"Activate"); + %player = %obj.triggeredBy; + %energy = %player.getEnergyLevel(); + %player.setCloaked(true); + %player.schedule(900, "setCloaked", false); + if (!%player.client.isAIControlled()) + buyFavorites(%player.client); + + %player.setEnergyLevel(%energy); +} + +/// -Mobile Base- ////////////////////////////////////////////////////////////// +//Function -- stationFinished(%data, %obj) +// %data = Station Data Block +// %obj = Station Object +//Decription -- Called when player has left the station +//////////////////////////////////////////////////////////////////////////////// +function MobileInvStation::stationFinished(%data, %obj) +{ + //Hide the Inventory Station GUI +} + +/// -Mobile Base- ////////////////////////////////////////////////////////////// +//Function -- getSound(%data, %forward) +// %data = Station Data Block +// %forward = direction the animation is playing +//Decription -- This sound will be played at the same time as the activate +// animation. +//////////////////////////////////////////////////////////////////////////////// +function MobileInvStation::getSound(%data, %forward) +{ + if(%forward) + return "MobileBaseInventoryActivateSound"; + else + return false; +} + +/// -Mobile Base- ////////////////////////////////////////////////////////////// +//Function -- setPlayerPosition(%data, %obj, %trigger, %colObj) +// %data = Station Data Block +// %obj = Station Object +// %trigger = Stations trigger +// %colObj = Object that is at the station +//Decription -- Called when player enters the trigger. Used to set the player +// in the center of the station. +//////////////////////////////////////////////////////////////////////////////// +function MobileInvStation::setPlayersPosition(%data, %obj, %trigger, %colObj) +{ + %vel = getWords(%colObj.getVelocity(), 0, 1) @ " 0"; + if((VectorLen(%vel) < 22) && (%obj.triggeredBy != %colObj)) + { + %pos = %trigger.position; + %colObj.setvelocity("0 0 0"); + %rot = getWords(%colObj.getTransform(),3, 6); + %pos = getWord(%pos,0) @ " " @ getWord(%pos,1) @ " " @ getWord(%pos,2)+0.8; + %terrain = getTerrainHeight2(%pos); + if (!(getWord(%pos,2) < getWord(%terrain,2) || %terrain $= "") || $Host::AllowUnderground) + //%colObj.setTransform(%pos @ " " @ %rot);//center player on object + return true; + } + return false; +} + +function MobileInvStation::onDamage() +{ +} + +function MobileInvStation::damageObject(%data, %targetObject, %sourceObject, %position, %amount, %damageType) +{ + //If vehicle station is hit then apply damage to the vehicle + %targetObject.getObjectMount().damage(%sourceObject, %position, %amount, %damageType); +} + +//////////////////////////////////////////////////////////////////////////////// +/// -Station Trigger- ////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + +////-Station Trigger-/////////////////////////////////////////////////////////// +//Function -- onEnterTrigger (%data, %obj, %colObj) +// %data = Trigger Data Block +// %obj = Trigger Object +// %colObj = Object that collided with the trigger +//Decription -- Called when trigger has been triggered +//////////////////////////////////////////////////////////////////////////////// +function stationTrigger::onEnterTrigger(%data, %obj, %colObj) +{ + //make sure it's a player object, and that that object is still alive + if(%colObj.getDataBlock().className !$= "Armor" || %colObj.getState() $= "Dead") + return; + + %colObj.inStation = true; + commandToClient(%colObj.client,'setStationKeys', true); + if(Game.stationOnEnterTrigger(%data, %obj, %colObj)) { + //verify station.team is team associated and isn't on player's team + if((%obj.mainObj.team != %colObj.client.team) && (%obj.mainObj.team != 0)) + { + //%obj.station.playAudio(2, StationAccessDeniedSound); + messageClient(%colObj.client, 'msgStationDenied', '\c2Access Denied -- Wrong team.~wfx/powered/station_denied.wav'); + } + else if(%obj.disableObj.isDisabled()) + { + messageClient(%colObj.client, 'msgStationDisabled', '\c2Station is disabled.'); + } + else if(!%obj.mainObj.isPowered()) + { + messageClient(%colObj.client, 'msgStationNoPower', '\c2Station is not powered.'); + } + else if(%obj.station.notDeployed) + { + messageClient(%colObj.client, 'msgStationNotDeployed', '\c2Station is not deployed.'); + } + else if(%obj.station.triggeredBy $= "") + { + if(%obj.station.getDataBlock().setPlayersPosition(%obj.station, %obj, %colObj)) + { + messageClient(%colObj.client, 'CloseHud', "", 'inventoryScreen'); + commandToClient(%colObj.client, 'TogglePlayHuds', true); + %obj.station.triggeredBy = %colObj; + %obj.station.getDataBlock().stationTriggered(%obj.station, 1); + %colObj.station = %obj.station; + %colObj.lastWeapon = ( %colObj.getMountedImage($WeaponSlot) == 0 ) ? "" : %colObj.getMountedImage($WeaponSlot).getName().item; + %colObj.unmountImage($WeaponSlot); + } + } + } +} + + +////-Station Trigger-/////////////////////////////////////////////////////////// +//Function -- onLeaveTrigger (%data, %obj, %colObj) +// %data = Trigger Data Block +// %obj = Trigger Object +// %colObj = Object that collided with the trigger +//Decription -- Called when trigger has been untriggered +//////////////////////////////////////////////////////////////////////////////// +function stationTrigger::onLeaveTrigger(%data, %obj, %colObj) +{ + if(%colObj.getDataBlock().className !$= "Armor") + return; + + %colObj.inStation = false; + commandToClient(%colObj.client,'setStationKeys', false); + if(%obj.station) + { + if(%obj.station.triggeredBy == %colObj) + { + %obj.station.getDataBlock().stationFinished(%obj.station); + %obj.station.getDataBlock().endRepairing(%obj.station); + %obj.station.triggeredBy = ""; + %obj.station.getDataBlock().stationTriggered(%obj.station, 0); + + if(!%colObj.teleporting) + %colObj.station = ""; + if(%colObj.getMountedImage($WeaponSlot) == 0 && !%colObj.teleporting) + { + if(%colObj.inv[%colObj.lastWeapon]) + %colObj.use(%colObj.lastWeapon); + + if(%colObj.getMountedImage($WeaponSlot) == 0) + %colObj.selectWeaponSlot( 0 ); + } + } + } +} + +////-Station Trigger-/////////////////////////////////////////////////////////// +//Function -- stationTriggered(%data, %obj, %isTriggered) +// %data = Station Data Block +// %obj = Station Object +// %isTriggered = 1 if triggered; 0 if status changed to +// untriggered +//Decription -- Called when a "station trigger" has been triggered or +// untriggered +//////////////////////////////////////////////////////////////////////////////// +function Station::stationTriggered(%data, %obj, %isTriggered) +{ + + + if(%isTriggered) + { + %obj.setThreadDir($ActivateThread, TRUE); + %obj.playThread($ActivateThread,"activate"); + %obj.playAudio($ActivateSound, %data.getSound(true)); + %obj.inUse = "Up"; + } + else + { + if(%obj.getDataBlock().getName() !$= StationVehicle) + { + %obj.stopThread($ActivateThread); + if(%obj.getObjectMount()) + %obj.getObjectMount().stopThread($ActivateThread); + %obj.inUse = "Down"; + } + else + { + %obj.setThreadDir($ActivateThread, FALSE); + %obj.playThread($ActivateThread,"activate"); + %obj.playAudio($ActivateSound, %data.getSound(false)); + %obj.inUse = "Down"; + } + } +} + +////-Station-/////////////////////////////////////////////////////////////////// +//Function -- onEndSequence(%data, %obj, %thread) +// %data = Station Data Block +// %obj = Station Object +// %thread = Thread number that the animation is associated +// with / running on. +//Decription -- Called when an animation sequence is finished playing +//////////////////////////////////////////////////////////////////////////////// +function Station::onEndSequence(%data, %obj, %thread) +{ + if(%thread == $ActivateThread) + { + if(%obj.inUse $= "Up") + { + %data.stationReady(%obj); + %player = %obj.triggeredBy; + if(%data.doesRepair && !%player.stationRepairing && %player.getDamageLevel() != 0) { + %oldRate = %player.getRepairRate(); + %player.setRepairRate(%oldRate + 0.00625); + %player.stationRepairing = 1; + } + } + else + { + if(%obj.getDataBlock().getName() !$= MobileInvStation) + { + %obj.stopThread($ActivateThread); + %obj.inUse = "Down"; + } + } + } + Parent::onEndSequence(%data, %obj, %thread); +} + +////-Station-/////////////////////////////////////////////////////////////////// +//Function -- onCollision(%data, %obj, %colObj) +// %data = Station Data Block +// %obj = Station Object +// %colObj = Object that collided with the station +//Decription -- Called when an object collides with a station +//////////////////////////////////////////////////////////////////////////////// +function Station::onCollision(%data, %obj, %colObj) +{ + // Currently Not Needed +} + +////-Station-/////////////////////////////////////////////////////////////////// +//Function -- endRepairing(%data, %obj) +// %data = Station Data Block +// %obj = Station Object +//Decription -- Called to stop repairing the object +//////////////////////////////////////////////////////////////////////////////// +function Station::endRepairing(%data, %obj) +{ + if(%obj.triggeredBy.stationRepairing) + { + %oldRate = %obj.triggeredBy.getRepairRate(); + %obj.triggeredBy.setRepairRate(%oldRate - 0.00625); + %obj.triggeredBy.stationRepairing = 0; + } +} + +////-Station Trigger-/////////////////////////////////////////////////////////// +//Function -- onTickTrigger(%data, %obj) +// %data = Trigger Data Block +// %obj = Trigger Object +//Decription -- Called every tick if triggered +//////////////////////////////////////////////////////////////////////////////// +function stationTrigger::onTickTrigger(%data, %obj) +{ +} + +//****************************************************************************** +//* Station General - Functions * +//****************************************************************************** + +//function Station::onGainPowerEnabled(%data, %obj) + +function Station::onLosePowerDisabled(%data, %obj) { + if (shouldChangePowerState(%obj,false)) { + // check to see if a player was using this station + %occupied = %obj.triggeredBy; + if(%occupied > 0) { + if(%data.doesRepair) + %data.endRepairing(%obj); + // if it's a deployed station, stop "flashing panels" thread + if(%data.getName() $= DeployedStationInventory) + %obj.stopThread($ActivateThread); + // reset some attributes + %occupied.setCloaked(false); + %occupied.station = ""; + %occupied.inStation = false; + %obj.triggeredBy = ""; + // restore "toggle inventory hud" key + commandToClient(%occupied.client,'setStationKeys', false); + // re-mount last weapon or weapon slot 0 + if(%occupied.getMountedImage($WeaponSlot) == 0) { + // ---------------------------------------------- + // z0dd - ZOD, 5/8/02. Optimized. + //if(%occupied.inv[%occupied.lastWeapon]) + // %occupied.use(%occupied.lastWeapon); + //if(%occupied.getMountedImage($WeaponSlot) == 0) + // %occupied.selectWeaponSlot( 0 ); + if(%occupied.inv[%occupied.lastWeapon]) + %occupied.use(%occupied.lastWeapon); + else + %occupied.selectWeaponSlot( 0 ); + // End z0dd - ZOD + // ---------------------------------------------- + } + } + } + Parent::onLosePowerDisabled(%data, %obj); +} + +// ----------------------------------------------------------------------------- +// z0dd - ZOD - Founder(founder@mechina.com), 5/8/02. Totall re-write of Vehicle +// station creation. More stable, addresses some power related bugs. + +// These are not needed anymore. +//function StationVehiclePad::gainPower(%data, %obj) +//{ +// %obj.station.setSelfPowered(); +// Parent::gainPower(%data, %obj); +//} + +//function StationVehiclePad::losePower(%data, %obj) +//{ +// %obj.station.clearSelfPowered(); +// Parent::losePower(%data, %obj); +//} +// End z0dd - ZOD - Founder +// ----------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// DeployedStationInventory: +//--------------------------------------------------------------------------- + +function DeployedStationInventory::stationReady(%data, %obj) +{ + %obj.notReady = 1; + %player = %obj.triggeredBy; + %obj.playThread($ActivateThread,"activate1"); + // function below found in inventoryHud.cs + if (!%player.client.isAIControlled()) + buyDeployableFavorites(%player.client); +} + +function DeployedStationInventory::stationFinished(%data, %obj) +{ +} + +function DeployedStationInventory::setPlayersPosition(%data, %obj, %trigger, %colObj) +{ + %vel = getWords(%colObj.getVelocity(), 0, 1) @ " 0"; + if((VectorLen(%vel) < 22) && (%obj.triggeredBy != %colObj)) + { + // build offset for player position + %rot = getWords(%obj.getTransform(), 3, 6); + %pos = getWords(%colObj.getTransform(),0,2); + %terrain = getTerrainHeight2(%pos); + if (!(getWord(%pos,2) < getWord(%terrain,2) || %terrain $= "") || $Host::AllowUnderground) + //%colObj.setTransform( %pos @ " " @ %rot ); + return true; + } + return false; +} + +function DeployedStationInventory::onDestroyed(%data, %obj, %prevState) +{ + if (%obj.isRemoved) + return; + %obj.isRemoved = true; + %obj.trigger.delete(); + // decrement team deployed count for this item + $TeamDeployedCount[%obj.team, InventoryDeployable]--; + + // when a station is destroyed, we don't need its trigger any more + remDSurface(%obj); + %obj.schedule(700, "delete"); + Parent::onDestroyed(%data, %obj, %prevState); +} + +function StationInventory::onDestroyed(%data,%obj,%prevState) { + if (%obj.isRemoved) + return; + if (%obj.deployed && ($Host::InvincibleDeployables != 1 || %obj.damageFailedDecon)) { + %obj.isRemoved = true; + %obj.trigger.delete(); + $TeamDeployedCount[%obj.team,LargeInventoryDeployable]--; + remDSurface(%obj); + %obj.schedule(500,"delete"); + } + Parent::onDestroyed(%data,%obj,%prevState); +} + +/// -Deployable Inventory- ////////////////////////////////////////////////////////////// +//Function -- getSound(%data, %forward) +// %data = Station Data Block +// %forward = direction the animation is playing +//Decription -- This sound will be played at the same time as the activate +// animation. +//////////////////////////////////////////////////////////////////////////////// +function DeployedStationInventory::getSound(%data, %forward) +{ + if(%forward) + return "DepInvActivateSound"; + else + return false; +} + +function StationInventory::disassemble(%data,%plyr,%obj) { + %pl = %obj.triggeredBy; + %cl = %pl.client; + if (isObject(%cl)) { + serverCmdResetControlObject(%cl); + if (isObject(%pl)) { + %pl.inStation = ""; + if (!%pl.getMountedImage($WeaponSlot)) { + if (%pl.inv[%pl.lastWeapon]) + %pl.use(%pl.lastWeapon); + if (%pl.getMountedImage($WeaponSlot) == 0) + %pl.selectWeaponSlot(0); + } + } + } + disassemble(%data,%plyr,%obj); +} + +function DeployedStationInventory::disassemble(%data,%plyr,%obj) { + // Use same code as Large Inventory Station + StationInventory::disassemble(%data,%plyr,%obj); +} diff --git a/scripts/truPhysics.cs b/scripts/truPhysics.cs new file mode 100644 index 0000000..cfb4812 --- /dev/null +++ b/scripts/truPhysics.cs @@ -0,0 +1,238 @@ +// TruPhysics engine v0.6 - physics engine by DynaBlade +// Mainly used for vehicles but can be expanded. + +// String Table +$TruPhysics::Enabled = true; +$TruPhysics::maxVelocity = 1500; // 1500 m/s or about 5400 KPH, T2's universal speed limit + +function capVelocity(%vel) +{ + if(velToSingle(%vel) > $TruPhysics::maxVelocity) + return $TruPhysics::maxVelocity; + else + return mFloor(%vel); +} + +function VehicleData::onCollision(%data,%obj,%col,%mod,%pos,%normal) +{ + + if(%data.disablePhysics || !$TruPhysics::Enabled) // !enabled = default vehicle physics, local or global scope + return; + + %className = %data.className; + + if(%col.isPlayer()) // player is dead and wants to be run over / annihilated. + { + %mass = -0.25 * %col.getMass(); + %vec = vectorScale(vectorScale(%col.getVelocity(), 0.25), %mass); + %obj.applyImpulse(%col.getPosition(), %vec); + } + else if(%col.isVehicle()) // phreakynasty! + { + if(%col.getDamageState() $= "Destroyed") // nothing to collide with here, get back to movement! + return; + + %AMass = %obj.getMass(); + %AiVec = vectorScale(%obj.getVelocity(), %mass); + %APos = vectorNormalize(%obj.getForwardVector()); + + %BMass = %obj.getMass(); + %BiVec = vectorScale(%obj.getVelocity(), %mass); + %BPos = vectorNormalize(%obj.getForwardVector()); + + %obj.applyImpulse(%BPos, %BiVec); + %col.applyImpulse(%APos, %AiVec); + } +} + + +function checkWaterPhysics(%obj) +{ + + if(%obj.isWet) + { + // water absorbs about 75% of your velocity when you hit it. + %mass = %obj.getMass() * 0.75; + %iVec = vectorScale(%obj.getVelocity(), %mass); + %obj.applyImpulse(%obj.getTransform(), %iVec); + + // speed tolerance checking (in KPH) + %mass = %obj.getMass(); + %pct = %obj.getDamagePct() / 4; + %max = %pct * (%data.minDrag * 10); + %maxSpeed = %max - (%mass / getRandom(10, 12)); + %vel = msToKPH(velToSingle(%obj.getVelocity())); + + if(%maxSpeed > %vel) + %obj.getDatablock().damageObject(%obj, 0, "0 0 0", %maxSpeed - %vel, $DamageType::Default); + + schedule(100, %obj, "checkWaterPhysics", %obj); + } +} + +function VehicleData::onEnterLiquid(%data, %obj, %coverage, %type) +{ + if(!%data.disableWaterPhysics && $TruPhysics::Enabled) + { + %obj.isWet = true; + checkWaterPhysics(%obj); + } + + switch(%type) + { + case 0: + //Water + %obj.setHeat(0.0); + case 1: + //Ocean Water + %obj.setHeat(0.0); + case 2: + //River Water + %obj.setHeat(0.0); + case 3: + //Stagnant Water + %obj.setHeat(0.0); + case 4: + //Lava + %obj.liquidDamage(%data, $VehicleDamageLava, $DamageType::Lava); + case 5: + //Hot Lava + %obj.liquidDamage(%data, $VehicleDamageHotLava, $DamageType::Lava); + case 6: + //Crusty Lava + %obj.liquidDamage(%data, $VehicleDamageCrustyLava, $DamageType::Lava); + case 7: + //Quick Sand + } +} + +function VehicleData::onLeaveLiquid(%data, %obj, %type) +{ + %obj.isWet = false; + // exiting from the water becomes easier if your engines are on... speed doubles? + if(!%data.disableWaterPhysics && $TruPhysics::Enabled) + { + %mass = %obj.getMass() * 0.375; + %iVec = capVel(vectorScale(%obj.getVelocity(), %mass)); + %obj.applyImpulse(%obj.getTransform(), %iVec); + } + + switch(%type) + { + case 0: + //Water + %obj.setHeat(1.0); + case 1: + //Ocean Water + %obj.setHeat(1.0); + case 2: + //River Water + %obj.setHeat(1.0); + case 3: + //Stagnant Water + %obj.setHeat(1.0); + case 4: + //Lava + case 5: + //Hot Lava + case 6: + //Crusty Lava + case 7: + //Quick Sand + } + + if(%obj.lDamageSchedule !$= "") + { + cancel(%obj.lDamageSchedule); + %obj.lDamageSchedule = ""; + } +} + +datablock AudioProfile(EngineAlertSound) +{ + filename = "gui/vote_nopass.WAV"; + description = AudioExplosion3d; + preload = true; +}; + +function VDUndo(%obj) +{ + %obj.vdOverride = false; + %obj.dmgApplyImp = false; +} + +function vDmgApplyImpulse(%obj) +{ + if(%obj.getDatablock().forceSensitive) + return; + + %obj.dmgApplyImp = true; + %lastPct = %obj.lastDmgPct; + %pct = %obj.getDamagePct(); + + if(%lastPct > %pct) + { + %obj.vdOverride = true; + schedule(1000, 0, "VDUndo", %obj); + } + + %obj.tp_sndCnt++; + + if(((%pct >= 0.5 && %pct < 1) && (%obj.vdOverride == false || %obj.vdOverride == "")) && %obj.augType !$= "Auto Repair Bot") + { + %force = (%pct * 500) * getRandom(1); + if(%force) + { + %va = getRandom(1) ? getRandom() * -1 : getRandom(); + %vb = getRandom(1) ? getRandom() * -1 : getRandom(); + %vc = getRandom(1) ? getRandom() * -1 : getRandom(); + %vec = %va SPC %vb SPC %vc; + %nVec = vectorScale(%vec, %force); + + %seed = getRandom(100); + if(%seed > 60 && %seed < 90) + %obj.playThread(0, "maintainback"); + else if(%seed > 90) + %obj.playThread(0, "maintainbot"); + else + %obj.playThread(0, "activateback"); + + %obj.applyImpulse(%obj.getTransform(), %nVec); + } + %obj.lastDmgPct = %pct; + schedule(250, %obj, "vDmgApplyImpulse", %obj); + + if(%obj.tp_sndCnt >= 4) + { + %obj.tp_sndCnt = 0; + %obj.play3D(EngineAlertSound); + } + } + else + %obj.stopThread(0); +} + +function VehicleData::onDamage(%this,%obj) +{ + + %damage = %obj.getDamageLevel(); + if (%damage >= %this.destroyedLevel) + { + if(%obj.getDamageState() !$= "Destroyed") + { + if(%obj.respawnTime !$= "") + %obj.marker.schedule = %obj.marker.data.schedule(%obj.respawnTime, "respawn", %obj.marker); + %obj.setDamageState(Destroyed); + } + } + else + { + if(%obj.getDamageState() !$= "Enabled") + %obj.setDamageState(Enabled); + + %pct = %obj.getDamagePct(); + + if(%pct >= 0.6 && !%obj.dmgApplyImp) + vDmgApplyImpulse(%obj); + } +} diff --git a/scripts/turret.cs b/scripts/turret.cs new file mode 100644 index 0000000..b997946 --- /dev/null +++ b/scripts/turret.cs @@ -0,0 +1,382 @@ +// sounds and effects +/////////////////////// +datablock EffectProfile(DeployableExplosionEffect) +{ + effectname = "explosions/explosion.xpl10"; + minDistance = 10; + maxDistance = 50; +}; + +datablock AudioProfile(DeployablesExplosionSound) +{ + filename = "fx/explosions/deployables_explosion.wav"; + description = AudioExplosion3d; + preload = true; + effect = DeployableExplosionEffect; +}; + +//-------------------------------------------------------------------------- +// Shockwave +//-------------------------------------------------------------------------- +datablock ShockwaveData(TurretShockwave) +{ + width = 6.0; + numSegments = 20; + numVertSegments = 2; + velocity = 8; + acceleration = 20.0; + lifetimeMS = 1500; + height = 1.0; + verticalCurve = 0.5; + + mapToTerrain = false; + renderBottom = true; + + 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.8 0.8 0.8 1.00"; + colors[1] = "0.8 0.5 0.2 0.20"; + colors[2] = "1.0 0.5 0.5 0.0"; +}; + +//-------------------------------------------------------------------------- +// Explosion +//-------------------------------------------------------------------------- +datablock ExplosionData(TurretExplosion) +{ + explosionShape = "effect_plasma_explosion.dts"; + soundProfile = ShapeExplosionSound; + faceViewer = true; + shockwave = TurretShockwave; +}; + +datablock ExplosionData(SmallTurretExplosion) +{ + soundProfile = DeployablesExplosionSound; + faceViewer = true; + + explosionShape = "effect_plasma_explosion.dts"; + sizes[0] = "0.3 0.3 0.3"; + sizes[1] = "0.3 0.3 0.3"; + times[0] = 0; + times[1] = 1; +}; + + +//-------------------------------------------------------------------------- +// Turret Debris +//-------------------------------------------------------------------------- +datablock DebrisData( TurretDebris ) +{ + explodeOnMaxBounce = false; + + elasticity = 0.20; + friction = 0.5; + + lifetime = 17.0; + lifetimeVariance = 0.0; + + minSpinSpeed = 60; + maxSpinSpeed = 600; + + numBounces = 10; + bounceVariance = 0; + + staticOnMaxBounce = true; + + useRadiusMass = true; + baseRadius = 0.4; + + velocity = 9.0; + velocityVariance = 4.5; +}; + +datablock DebrisData( TurretDebrisSmall ) +{ + explodeOnMaxBounce = false; + + elasticity = 0.20; + friction = 0.5; + + lifetime = 17.0; + lifetimeVariance = 0.0; + + minSpinSpeed = 60; + maxSpinSpeed = 600; + + numBounces = 10; + bounceVariance = 0; + + staticOnMaxBounce = true; + + useRadiusMass = true; + baseRadius = 0.2; + + velocity = 5.0; + velocityVariance = 2.5; +}; + + +//-------------------------------------------------------------------------- +// Turret base class functionality. Barrels are in scripts/weapons/*.cs +// +// +//-------------------------------------------------------------------------- + +function GameBaseData::hasLOS() { + return 1; +} + +function TurretData::create(%block) +{ + %obj = new Turret() { + dataBlock = %block; + }; + + return %obj; +} + +datablock SensorData(TurretBaseSensorObj) +{ + detects = true; + detectsUsingLOS = true; + detectsPassiveJammed = false; + detectsActiveJammed = false; + detectsCloaked = false; + detectionPings = true; + detectRadius = 80; +}; + + +datablock TurretData(TurretBaseLarge) : TurretDamageProfile +{ + className = TurretBase; + catagory = "Turrets"; + shapeFile = "turret_base_large.dts"; + preload = true; + + mass = 1.0; // Not really relevant + + maxDamage = 2.25; + destroyedLevel = 2.25; + disabledLevel = 1.35; + explosion = TurretExplosion; + expDmgRadius = 15.0; + expDamage = 0.66; + expImpulse = 2000.0; + repairRate = 0.5; + emap = true; + + thetaMin = 15; + thetaMax = 140; + + isShielded = true; + energyPerDamagePoint = 50; + maxEnergy = 150; + rechargeRate = 0.31; + humSound = SensorHumSound; + pausePowerThread = true; + + canControl = true; + cmdCategory = "Tactical"; + cmdIcon = CMDTurretIcon; + cmdMiniIconName = "commander/MiniIcons/com_turretbase_grey"; + targetNameTag = 'Base'; + targetTypeTag = 'Turret'; + sensorData = TurretBaseSensorObj; + sensorRadius = TurretBaseSensorObj.detectRadius; + sensorColor = "0 212 45"; + heatSignature = 1.0; + firstPersonOnly = true; + + debrisShapeName = "debris_generic.dts"; + debris = TurretDebris; +}; + +function TurretData::onGainPowerEnabled(%data, %obj) { + if (shouldChangePowerState(%obj,true)) + setTargetSensorData(%obj.target, %data.sensorData); + Parent::onGainPowerEnabled(%data, %obj); +} + +function TurretData::onLosePowerDisabled(%data, %obj) { + if (shouldChangePowerState(%obj,false)) { + // Must kick players out of turret + %obj.clearTarget(); + setTargetSensorData(%obj.target, 0); + } + Parent::onLosePowerDisabled(%data, %obj); +} + +function TurretData::selectTarget(%this, %turret) { + %turretTarg = %turret.getTarget(); + if(%turretTarg == -1) + return; + + // if the turret isn't on a team, don't fire at anyone + if(getTargetSensorGroup(%turretTarg) == 0) { + %turret.clearTarget(); + return; + } + + // stop firing if turret is disabled or if it needs power and isn't powered + if((!%turret.isPowered()) && (!%turret.needsNoPower)) { + %turret.clearTarget(); + return; + } + + if ($Host::Purebuild == 1 && $TurretEnableOverride != 1) { + %turret.clearTarget(); + return; + } + + %TargetSearchMask = $TypeMasks::PlayerObjectType | $TypeMasks::VehicleObjectType | $TypeMasks::StationObjectType | $TypeMasks::GeneratorObjectType | + $TypeMasks::SensorObjectType | $TypeMasks::TurretObjectType; //$TypeMasks::StaticObjectType; + + InitContainerRadiusSearch(%turret.getMuzzlePoint(0), + %turret.getMountedImage(0).attackRadius, + %TargetSearchMask); + + // TODO - clean up this mess + GameBaseData::hasLOS() + + while ((%potentialTarget = ContainerSearchNext()) != 0) { + if (%potentialtarget) { + %potTargTarg = %potentialTarget.getTarget(); + if (%turret.isValidTarget(%potentialTarget) + && (getTargetSensorGroup(%turretTarg) != getTargetSensorGroup(%potTargTarg)) + && (getTargetSensorGroup(%potTargTarg) != 0) + && ((%potentialTarget.getType() & $TypeMasks::PlayerObjectType) || !$TurretOnlyTargetPlayers) + && %this.hasLOS(%turret,0,%potentialTarget)) { + if (%potentialTarget.homingCount > 0 && !%secondTarg) { + if (!%firstTarg) + %firstTarg = %potentialTarget; + else + %secondTarg = %potentialTarget; + } + else { + %turret.setTargetObject(%potentialTarget); + %turret.aquireTime = getSimTime(); + return; + } + } + } + } + if (%secondTarg) { + %turret.setTargetObject(%firstTarg); + %turret.aquireTime = getSimTime(); + return; + } + if (%firstTarg) { + %turret.setTargetObject(%firstTarg); + %turret.aquireTime = getSimTime(); + return; + } +} + +function TurretData::replaceCallback(%this, %turret, %engineer) +{ + // This is a valid replacement. First, let's see if the engineer + // still has the correct pack in place... + if (%engineer.getMountedImage($BackPackSlot) != 0) + { + %barrel = %engineer.getMountedImage($BackPackSlot).turretBarrel; + if (%barrel !$= "") + { + // if there was a barrel there before, get rid of it + %turret.unmountImage(0); + // remove the turret barrel pack + %engineer.setInventory(%engineer.getMountedImage($BackPackSlot).item, 0); + // mount new barrel on base + %turret.mountImage(%barrel, 0, false); + } + else + { + // Player doesn't have the correct pack on... + } + } + else + { + // Player doesn't have any pack on... + } +} + +function TurretData::onDestroyed(%this, %turret, %prevState) +{ + if( isObject( %turret.lastProjectile ) ) + %turret.lastProjectile.delete(); + + Parent::onDestroyed(%this, %turret, %prevState); +} + +function checkTurretMount(%data, %obj, %slot) +{ + // search for a turret base in player's LOS + %eyeVec = VectorNormalize(%obj.getEyeVector()); + %srchRange = VectorScale(%eyeVec, 5.0); // look 5m for a turret base + %plTm = %obj.getEyeTransform(); + %plyrLoc = firstWord(%plTm) @ " " @ getWord(%plTm, 1) @ " " @ getWord(%plTm, 2); + %srchEnd = VectorAdd(%plyrLoc, %srchRange); + %potTurret = ContainerRayCast(%obj.getEyeTransform(), %srchEnd, $TypeMasks::TurretObjectType); + if(%potTurret != 0) + { + %otherMountObj = "foo"; + + if(%potTurret.getDatablock().getName() $= "TurretBaseLarge" + || %potTurret.getDatablock().getName() $= %otherMountObj + || %potTurret.getDatablock().getName() $= "TurretDeployedBase") + { + // found a turret base, what team is it on? + if(%potTurret.team == %obj.client.team) + { + if(%potTurret.getDamageState() !$= "Enabled") + { + // the base is destroyed + messageClient(%obj.client, 'MsgBaseDestroyed', "\c2Turret base is disabled, cannot mount barrel."); + %obj.setImageTrigger($BackpackSlot, false); + } + else + { + // it's a functional turret base on our team! stick the barrel on it + messageClient(%obj.client, 'MsgTurretMount', "\c2Mounting barrel pack on turret base."); + serverPlay3D(TurretPackActivateSound, %potTurret.getTransform()); + %potTurret.initiateBarrelSwap(%obj); + } + } + else + { + // whoops, wrong team + messageClient(%obj.client, 'MsgTryEnemyTurretMount', "\c2Cannot mount a barrel on an enemy turret base!"); + %obj.setImageTrigger($BackpackSlot, false); + } + } + else + { + // tried to mount barrel on some other turret type + messageClient(%obj.client, 'MsgNotTurretBase', "\c2Can only mount a barrel on a turret base."); + %obj.setImageTrigger($BackpackSlot, false); + } + } + else + { + // I don't see any turret + messageClient(%obj.client, 'MsgNoTurretBase', "\c2No turret within range."); + %obj.setImageTrigger($BackpackSlot, false); + } +} + +//-------------------------------------- Load Barrel Images +// +exec("scripts/turrets/mortarBarrelLarge.cs"); +exec("scripts/turrets/aaBarrelLarge.cs"); +exec("scripts/turrets/missileBarrelLarge.cs"); +exec("scripts/turrets/plasmaBarrelLarge.cs"); +exec("scripts/turrets/ELFBarrelLarge.cs"); +exec("scripts/turrets/outdoorDeployableBarrel.cs"); +exec("scripts/turrets/indoorDeployableBarrel.cs"); +exec("scripts/turrets/sentryTurret.cs"); \ No newline at end of file diff --git a/scripts/turrets/indoorDeployableBarrel.cs b/scripts/turrets/indoorDeployableBarrel.cs new file mode 100644 index 0000000..0240cde --- /dev/null +++ b/scripts/turrets/indoorDeployableBarrel.cs @@ -0,0 +1,328 @@ +datablock EffectProfile(IBLSwitchEffect) +{ + effectname = "powered/turret_light_activate"; + minDistance = 5.0; + maxDistance = 5.0; +}; + +datablock EffectProfile(IBLFireEffect) +{ + effectname = "powered/turret_indoor_fire"; + minDistance = 2.5; + maxDistance = 5.0; +}; + +datablock AudioProfile(IBLSwitchSound) +{ + filename = "fx/powered/turret_light_activate.wav"; + description = AudioClose3d; + preload = true; + effect = IBLSwitchEffect; +}; + +datablock AudioProfile(IBLFireSound) +{ + filename = "fx/powered/turret_indoor_fire.wav"; + description = AudioDefault3d; + preload = true; + effect = IBLFireEffect; +}; + +datablock SensorData(DeployedIndoorTurretSensor) +{ + detects = true; + detectsUsingLOS = true; + detectsPassiveJammed = false; + detectsActiveJammed = false; + detectsCloaked = false; + detectionPings = true; + detectRadius = 40; +}; + +datablock ShockwaveData(IndoorTurretMuzzleFlash) +{ + width = 0.5; + numSegments = 13; + numVertSegments = 1; + velocity = 2.0; + acceleration = -1.0; + lifetimeMS = 300; + height = 0.1; + verticalCurve = 0.5; + + mapToTerrain = false; + renderBottom = false; + orientToNormal = true; + renderSquare = true; + + texture[0] = "special/blasterHit"; + texture[1] = "special/gradient"; + texWrap = 3.0; + + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; + + colors[0] = "1.0 0.3 0.3 1.0"; + colors[1] = "1.0 0.3 0.3 1.0"; + colors[2] = "1.0 0.3 0.3 0.0"; +}; + +datablock TurretData(TurretDeployedFloorIndoor) : TurretDamageProfile +{ + className = DeployedTurret; + shapeFile = "turret_indoor_deployf.dts"; + + mass = 5.0; + maxDamage = 0.5; + destroyedLevel = 0.5; + disabledLevel = 0.21; + explosion = SmallTurretExplosion; + expDmgRadius = 5.0; + expDamage = 0.25; + expImpulse = 500.0; + repairRate = 0; + heatSignature = 0.0; + + deployedObject = true; + + thetaMin = 5; + thetaMax = 145; + thetaNull = 90; + + primaryAxis = zaxis; + + isShielded = true; + energyPerDamagePoint = 110; + maxEnergy = 30; + rechargeRate = 0.10; + barrel = DeployableIndoorBarrel; + + canControl = true; + cmdCategory = "DTactical"; + cmdIcon = CMDTurretIcon; + cmdMiniIconName = "commander/MiniIcons/com_turret_grey"; + targetNameTag = 'Spider Clamp'; + targetTypeTag = 'Turret'; + sensorData = DeployedIndoorTurretSensor; + sensorRadius = DeployedIndoorTurretSensor.detectRadius; + sensorColor = "191 0 226"; + + firstPersonOnly = true; + renderWhenDestroyed = true; + + debrisShapeName = "debris_generic_small.dts"; + debris = TurretDebrisSmall; +}; + +datablock TurretData(TurretDeployedWallIndoor) : TurretDamageProfile +{ + className = DeployedTurret; + shapeFile = "turret_indoor_deployw.dts"; + + mass = 5.0; + maxDamage = 0.5; + destroyedLevel = 0.5; + disabledLevel = 0.21; + explosion = SmallTurretExplosion; + expDmgRadius = 5.0; + expDamage = 0.25; + expImpulse = 500.0; + repairRate = 0; + heatSignature = 0.0; + + thetaMin = 5; + thetaMax = 145; + thetaNull = 90; + + deployedObject = true; + + primaryAxis = yaxis; + + isShielded = true; + energyPerDamagePoint = 110; + maxEnergy = 30; + rechargeRate = 0.10; + barrel = DeployableIndoorBarrel; + + canControl = true; + cmdCategory = "DTactical"; + cmdIcon = CMDTurretIcon; + cmdMiniIconName = "commander/MiniIcons/com_turret_grey"; + targetNameTag = 'Spider Clamp'; + targetTypeTag = 'Turret'; + sensorData = DeployedIndoorTurretSensor; + sensorRadius = DeployedIndoorTurretSensor.detectRadius; + sensorColor = "191 0 226"; + + firstPersonOnly = true; + renderWhenDestroyed = true; + + debrisShapeName = "debris_generic_small.dts"; + debris = TurretDebrisSmall; +}; + +datablock TurretData(TurretDeployedCeilingIndoor) : TurretDamageProfile +{ + className = DeployedTurret; + shapeFile = "turret_indoor_deployc.dts"; + + mass = 5.0; + maxDamage = 0.5; + destroyedLevel = 0.5; + disabledLevel = 0.21; + explosion = SmallTurretExplosion; + expDmgRadius = 5.0; + expDamage = 0.25; + expImpulse = 500.0; + repairRate = 0; + explosion = SmallTurretExplosion; + + //thetaMin = 5; + //thetaMax = 145; + thetaMin = 35; + thetaMax = 175; + thetaNull = 90; + heatSignature = 0.0; + + deployedObject = true; + + primaryAxis = revzaxis; + + isShielded = true; + energyPerDamagePoint = 110; + maxEnergy = 30; + rechargeRate = 0.10; + barrel = DeployableIndoorBarrel; + + canControl = true; + cmdCategory = "DTactical"; + cmdIcon = CMDTurretIcon; + cmdMiniIconName = "commander/MiniIcons/com_turret_grey"; + targetNameTag = 'Spider Clamp'; + targetTypeTag = 'Turret'; + sensorData = DeployedIndoorTurretSensor; + sensorRadius = DeployedIndoorTurretSensor.detectRadius; + sensorColor = "191 0 226"; + + firstPersonOnly = true; + renderWhenDestroyed = true; + + debrisShapeName = "debris_generic_small.dts"; + debris = TurretDebrisSmall; +}; + +datablock LinearFlareProjectileData(IndoorTurretBolt) +{ + directDamage = 0.14; + directDamageType = $DamageType::IndoorDepTurret; + explosion = "BlasterExplosion"; + kickBackStrength = 0.0; + + dryVelocity = 120.0; + wetVelocity = 40.0; + velInheritFactor = 0.5; + fizzleTimeMS = 2000; + lifetimeMS = 3000; + explodeOnDeath = false; + reflectOnWaterImpactAngle = 0.0; + explodeOnWaterImpact = false; + deflectionOnWaterImpact = 0.0; + fizzleUnderwaterMS = 3000; + + numFlares = 20; + size = 0.45; + flareColor = "1 0.35 0.35"; + flareModTexture = "flaremod"; + flareBaseTexture = "flarebase"; + + sound = BlasterProjectileSound; + + hasLight = true; + lightRadius = 3.0; + lightColor = "1 0.35 0.35"; +}; + +datablock TurretImageData(DeployableIndoorBarrel) +{ + shapeFile = "turret_muzzlepoint.dts"; + // --------------------------------------------- + // z0dd - ZOD, 5/8/02. Incorrect parameter value + //item = IndoorTurretBarrel; + item = TurretIndoorDeployable; + + projectile = IndoorTurretBolt; + projectileType = LinearFlareProjectile; + + usesEnergy = true; + fireEnergy = 4.5; + minEnergy = 4.5; + + lightType = "WeaponFireLight"; + lightColor = "0.25 0.15 0.15 1.0"; + lightTime = "1000"; + lightRadius = "2"; + + muzzleFlash = IndoorTurretMuzzleFlash; + + // Turret parameters + activationMS = 150; + deactivateDelayMS = 300; + thinkTimeMS = 150; + degPerSecTheta = 580; + degPerSecPhi = 960; + attackRadius = 60; + + // State transitions + stateName[0] = "Activate"; + stateTransitionOnNotLoaded[0] = "Dead"; + stateTransitionOnLoaded[0] = "ActivateReady"; + + stateName[1] = "ActivateReady"; + stateSequence[1] = "Activate"; + stateSound[1] = IBLSwitchSound; + stateTimeoutValue[1] = 1; + stateTransitionOnTimeout[1] = "Ready"; + stateTransitionOnNotLoaded[1] = "Deactivate"; + stateTransitionOnNoAmmo[1] = "NoAmmo"; + + stateName[2] = "Ready"; + stateTransitionOnNotLoaded[2] = "Deactivate"; + stateTransitionOnTriggerDown[2] = "Fire"; + stateTransitionOnNoAmmo[2] = "NoAmmo"; + + stateName[3] = "Fire"; + stateTransitionOnTimeout[3] = "Reload"; + stateTimeoutValue[3] = 0.3; + stateFire[3] = true; + stateShockwave[3] = true; + stateRecoil[3] = LightRecoil; + stateAllowImageChange[3] = false; + stateSequence[3] = "Fire"; + stateSound[3] = IBLFireSound; + stateScript[3] = "onFire"; + + stateName[4] = "Reload"; + stateTimeoutValue[4] = 0.8; + stateAllowImageChange[4] = false; + stateSequence[4] = "Reload"; + stateTransitionOnTimeout[4] = "Ready"; + stateTransitionOnNotLoaded[4] = "Deactivate"; + stateTransitionOnNoAmmo[4] = "NoAmmo"; + + stateName[5] = "Deactivate"; + stateSequence[5] = "Activate"; + stateDirection[5] = false; + stateTimeoutValue[5] = 1; + stateTransitionOnLoaded[5] = "ActivateReady"; + stateTransitionOnTimeout[5] = "Dead"; + + stateName[6] = "Dead"; + stateTransitionOnLoaded[6] = "ActivateReady"; + + stateName[7] = "NoAmmo"; + stateTransitionOnAmmo[7] = "Reload"; + stateSequence[7] = "NoAmmo"; +}; + + diff --git a/scripts/turrets/outdoorDeployableBarrel.cs b/scripts/turrets/outdoorDeployableBarrel.cs new file mode 100644 index 0000000..9445f3b --- /dev/null +++ b/scripts/turrets/outdoorDeployableBarrel.cs @@ -0,0 +1,254 @@ +// -------------------------------------------------------------- +// Outdoor Deployable Turret barrel +// -------------------------------------------------------------- + +// -------------------------------------------------------------- +// Sound datablocks +// -------------------------------------------------------------- +datablock EffectProfile(OBLSwitchEffect) +{ + effectname = "powered/turret_light_activate"; + minDistance = 2.5; + maxDistance = 5.0; +}; + +datablock EffectProfile(OBLFireEffect) +{ + effectname = "powered/turret_outdoor_fire"; + minDistance = 2.5; + maxDistance = 5.0; +}; + +datablock AudioProfile(OBLSwitchSound) +{ + filename = "fx/powered/turret_light_activate.wav"; + description = AudioClose3d; + preload = true; + effect = OBLSwitchEffect; +}; + +datablock AudioProfile(OBLFireSound) +{ + filename = "fx/powered/turret_outdoor_fire.wav"; + description = AudioDefault3d; + preload = true; + effect = OBLFireEffect; +}; + +// -------------------------------------------------------------- +// Projectile data +// -------------------------------------------------------------- + +datablock TracerProjectileData(FusionBolt) +{ + doDynamicClientHits = true; + + projectileShapeName = ""; + directDamage = 0.0; + directDamageType = $DamageType::OutdoorDepTurret; + hasDamageRadius = true; + indirectDamage = 0.24; + damageRadius = 4.0; + kickBackStrength = 0.0; + radiusDamageType = $DamageType::OutdoorDepTurret; + sound = BlasterProjectileSound; + explosion = PlasmaBoltExplosion; + + dryVelocity = 60.0; + wetVelocity = 40.0; + velInheritFactor = 1.0; + fizzleTimeMS = 4000; + lifetimeMS = 6000; + explodeOnDeath = false; + reflectOnWaterImpactAngle = 0.0; + explodeOnWaterImpact = true; + deflectionOnWaterImpact = 0.0; + fizzleUnderwaterMS = -1; + + activateDelayMS = 100; + + tracerLength = 5; + tracerAlpha = false; + tracerMinPixels = 3; + tracerColor = "1 0 0 1"; + tracerTex[0] = "special/landSpikeBolt"; + tracerTex[1] = "special/landSpikeBoltCross"; + tracerWidth = 0.35; + crossSize = 0.79; + crossViewAng = 0.990; + renderCross = true; + emap = true; +}; + +// -------------------------------------------------------------- + +datablock SensorData(DeployedOutdoorTurretSensor) +{ + detects = true; + detectsUsingLOS = true; + detectsPassiveJammed = false; + detectsActiveJammed = false; + detectsCloaked = false; + detectionPings = true; + detectRadius = 60; +}; + +datablock ShockwaveData(OutdoorTurretMuzzleFlash) +{ + width = 0.5; + numSegments = 13; + numVertSegments = 1; + velocity = 2.0; + acceleration = -1.0; + lifetimeMS = 300; + height = 0.1; + verticalCurve = 0.5; + + mapToTerrain = false; + renderBottom = false; + orientToNormal = true; + renderSquare = true; + + texture[0] = "special/blasterHit"; + texture[1] = "special/gradient"; + texWrap = 3.0; + + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; + + colors[0] = "1.0 0.8 0.5 1.0"; + colors[1] = "1.0 0.8 0.5 1.0"; + colors[2] = "1.0 0.8 0.5 0.0"; +}; + +datablock TurretData(TurretDeployedOutdoor) : TurretDamageProfile +{ + className = DeployedTurret; + shapeFile = "turret_outdoor_deploy.dts"; + + rechargeRate = 0.15; + + mass = 5.0; + maxDamage = 0.80; + destroyedLevel = 0.80; + disabledLevel = 0.35; + explosion = HandGrenadeExplosion; + expDmgRadius = 5.0; + expDamage = 0.3; + expImpulse = 500.0; + repairRate = 0; + + deployedObject = true; + + thetaMin = 0; + thetaMax = 145; + thetaNull = 90; + + yawVariance = 30.0; // these will smooth out the elf tracking code. + pitchVariance = 30.0; // more or less just tolerances + + isShielded = true; + energyPerDamagePoint = 110; + maxEnergy = 60; + renderWhenDestroyed = true; + barrel = DeployableOutdoorBarrel; + heatSignature = 0; + + canControl = true; + cmdCategory = "DTactical"; + cmdIcon = CMDTurretIcon; + cmdMiniIconName = "commander/MiniIcons/com_turret_grey"; + targetNameTag = 'Landspike'; + targetTypeTag = 'Turret'; + sensorData = DeployedOutdoorTurretSensor; + sensorRadius = DeployedOutdoorTurretSensor.detectRadius; + sensorColor = "191 0 226"; + + firstPersonOnly = true; + + debrisShapeName = "debris_generic_small.dts"; + debris = TurretDebrisSmall; +}; + +datablock TurretImageData(DeployableOutdoorBarrel) +{ + shapeFile = "turret_muzzlepoint.dts"; + // --------------------------------------------- + // z0dd - ZOD, 5/8/02. Incorrect parameter value + //item = OutdoorTurretBarrel; + item = TurretOutdoorDeployable; + + projectileType = TracerProjectile; + projectile = FusionBolt; + usesEnergy = true; + fireEnergy = 11.0; + minEnergy = 11.0; + + lightType = "WeaponFireLight"; + lightColor = "0.25 0.25 0.15 0.2"; + lightTime = "1000"; + lightRadius = "2"; + + muzzleFlash = OutdoorTurretMuzzleFlash; + + // Turret parameters + activationMS = 300; + deactivateDelayMS = 600; + thinkTimeMS = 200; + degPerSecTheta = 580; + degPerSecPhi = 960; + attackRadius = 100; + + // State transitions + stateName[0] = "Activate"; + stateTransitionOnNotLoaded[0] = "Dead"; + stateTransitionOnLoaded[0] = "ActivateReady"; + + stateName[1] = "ActivateReady"; + stateSequence[1] = "Activate"; + stateSound[1] = OBLSwitchSound; + stateTimeoutValue[1] = 1; + stateTransitionOnTimeout[1] = "Ready"; + stateTransitionOnNotLoaded[1] = "Deactivate"; + stateTransitionOnNoAmmo[1] = "NoAmmo"; + + stateName[2] = "Ready"; + stateTransitionOnNotLoaded[2] = "Deactivate"; + stateTransitionOnTriggerDown[2] = "Fire"; + stateTransitionOnNoAmmo[2] = "NoAmmo"; + + stateName[3] = "Fire"; + stateTransitionOnTimeout[3] = "Reload"; + stateTimeoutValue[3] = 0.3; + stateFire[3] = true; + stateShockwave[3] = true; + stateRecoil[3] = LightRecoil; + stateAllowImageChange[3] = false; + stateSequence[3] = "Fire"; + stateSound[3] = OBLFireSound; + stateScript[3] = "onFire"; + + stateName[4] = "Reload"; + stateTimeoutValue[4] = 1.2; + stateAllowImageChange[4] = false; + stateSequence[4] = "Reload"; + stateTransitionOnTimeout[4] = "Ready"; + stateTransitionOnNotLoaded[4] = "Deactivate"; + stateTransitionOnNoAmmo[4] = "NoAmmo"; + + stateName[5] = "Deactivate"; + stateSequence[5] = "Activate"; + stateDirection[5] = false; + stateTimeoutValue[5] = 1; + stateTransitionOnLoaded[5] = "ActivateReady"; + stateTransitionOnTimeout[5] = "Dead"; + + stateName[6] = "Dead"; + stateTransitionOnLoaded[6] = "ActivateReady"; + + stateName[7] = "NoAmmo"; + stateTransitionOnAmmo[7] = "Reload"; + stateSequence[7] = "NoAmmo"; +}; + diff --git a/scripts/vehicles/serverVehicleHud.cs b/scripts/vehicles/serverVehicleHud.cs new file mode 100644 index 0000000..700fdf6 --- /dev/null +++ b/scripts/vehicles/serverVehicleHud.cs @@ -0,0 +1,430 @@ +//------------------------------------------------------------------------------ +datablock EffectProfile(VehicleAppearEffect) +{ + effectname = "vehicles/inventory_pad_appear"; + minDistance = 5; + maxDistance = 10; +}; + +datablock EffectProfile(ActivateVehiclePadEffect) +{ + effectname = "powered/vehicle_pad_on"; + minDistance = 20; + maxDistance = 30; +}; + +datablock AudioProfile(VehicleAppearSound) +{ + filename = "fx/vehicles/inventory_pad_appear.wav"; + description = AudioClosest3d; + preload = true; + effect = VehicleAppearEffect; +}; + +datablock AudioProfile(ActivateVehiclePadSound) +{ + filename = "fx/powered/vehicle_pad_on.wav"; + description = AudioClose3d; + preload = true; + effect = ActivateVehiclePadEffect; +}; + +datablock StationFXVehicleData( VehicleInvFX ) +{ + lifetime = 6.0; + + glowTopHeight = 1.5; + glowBottomHeight = 0.1; + glowTopRadius = 12.5; + glowBottomRadius = 12.0; + numGlowSegments = 26; + glowFadeTime = 3.25; + + armLightDelay = 2.3; + armLightLifetime = 3.0; + armLightFadeTime = 1.5; + numArcSegments = 10.0; + + sphereColor = "0.1 0.1 0.5"; + spherePhiSegments = 13; + sphereThetaSegments = 8; + sphereRadius = 12.0; + sphereScale = "1.05 1.05 0.85"; + + glowNodeName = "GLOWFX"; + + leftNodeName[0] = "LFX1"; + leftNodeName[1] = "LFX2"; + leftNodeName[2] = "LFX3"; + leftNodeName[3] = "LFX4"; + + rightNodeName[0] = "RFX1"; + rightNodeName[1] = "RFX2"; + rightNodeName[2] = "RFX3"; + rightNodeName[3] = "RFX4"; + + + texture[0] = "special/stationGlow"; + texture[1] = "special/stationLight2"; +}; + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +function serverCmdBuyVehicle(%client, %blockName) +{ + %team = %client.getSensorGroup(); + if(vehicleCheck(%blockName, %team)) + { + %station = %client.player.station.pad; + if( (%station.ready) && (%station.station.vehicle[%blockName]) ) + { + %trans = %station.getTransform(); + %pos = getWords(%trans, 0, 2); + %matrix = VectorOrthoBasis(getWords(%trans, 3, 6)); + %yrot = getWords(%matrix, 3, 5); + %p = vectorAdd(%pos,vectorScale(%yrot, -3)); + + //%adjust = vectorMultiply(realVec(%station,"0 0 4"),"1 1 3"); + //%adjustUp = getWord(%adjust,2); + //%adjust = getWords(%adjust,0,1) SPC ((%adjustUp * 0.5) + (mAbs(%adjustUp) * -0.5)); + %p = VectorAdd(%p,RealVec(%station,"0 0 7")); + +// error(%blockName); +// error(%blockName.spawnOffset); + + + ///[Most] + ///Updated Build code for rotatable vehicle pad. + %p = vectorAdd(%p, RealVec(%station,VectorAdd(%blockName.spawnOffset,"0 0 1"))); + %forward = VectorCross(VectorCross("0 0 1",realvec(%station,"1 0 0")),"0 0 1"); + + %rot = FullRot("0 0 1",%forward); + %rrot = RotAdd(%rot,"0 0 1 3.14"); + //%rrot= %rot; + %rot = getWords(%rrot, 0,2); + %angle = getWord(%rrot, 3); + //[Most] + %mask = $TypeMasks::VehicleObjectType | $TypeMasks::PlayerObjectType | + $TypeMasks::StationObjectType | $TypeMasks::TurretObjectType; + InitContainerRadiusSearch(%p, %blockName.checkRadius, %mask); + + %clear = 1; + for (%x = 0; (%obj = containerSearchNext()) != 0; %x++) + { + if((%obj.getType() & $TypeMasks::VehicleObjectType) && (%obj.getDataBlock().checkIfPlayersMounted(%obj))) + { + %clear = 0; + break; + } + else + if (%obj !=%station.station) + %removeObjects[%x] = %obj; + } + if(%clear) + { + %fadeTime = 0; + for(%i = 0; %i < %x; %i++) + { + if(%removeObjects[%i].getType() & $TypeMasks::PlayerObjectType) + { + %pData = %removeObjects[%i].getDataBlock(); + %pData.damageObject(%removeObjects[%i], 0, "0 0 0", 1000, $DamageType::VehicleSpawn); + } + else + { + %removeObjects[%i].mountable = 0; + %removeObjects[%i].startFade( 1000, 0, true ); + %removeObjects[%i].schedule(1001, "delete"); + %fadeTime = 1500; + } + } + schedule(%fadeTime, 0, "createVehicle", %client, %station, %blockName, %team , %p, %rot, %angle); + } + else + MessageClient(%client, "", 'Can\'t create vehicle. A player is on the creation pad.'); + } + } +} + +function createVehicle(%client, %station, %blockName, %team , %pos, %rot, %angle) +{ + %obj = %blockName.create(%team); + if(%obj) + { + %station.ready = false; + %obj.team = %team; + %obj.useCreateHeight(true); + %obj.schedule(5500, "useCreateHeight", false); + %obj.getDataBlock().isMountable(%obj, false); + %obj.getDataBlock().schedule(6500, "isMountable", %obj, true); + vehicleListAdd(%blockName, %obj); + MissionCleanup.add(%obj); + + %turret = %obj.getMountNodeObject(10); + if(%turret > 0) + { + %turret.setCloaked(true); + %turret.schedule(4800, "setCloaked", false); + } + + %obj.setCloaked(true); + %obj.setTransform(%pos @ " " @ %rot @ " " @ %angle); + + %obj.schedule(3700, "playAudio", 0, VehicleAppearSound); + %obj.schedule(4800, "setCloaked", false); + + if(%client.player.lastVehicle) + { + %client.player.lastVehicle.lastPilot = ""; + vehicleAbandonTimeOut(%client.player.lastVehicle); + %client.player.lastVehicle = ""; + } + %client.player.lastVehicle = %obj; + %obj.lastPilot = %client.player; + %station.playAudio($ActivateSound, ActivateVehiclePadSound); + %ppos = VectorAdd(%station.getTransform(),RealVec(%station,"0 0 2")); + if (%station.getDatablock().getName() $= "DeployableVehiclePad") + { + %station.playThread($ActivateThread,"activate2"); + %up = realvec(%station,"0 0 1"); + %forward = realvec(%station,"1 0 0"); + %p1 = CreateEmitter(%ppos,DVPADE); + %p2 = CreateEmitter(%ppos,DVPADE); + %p1.setRotation(FullRot(%up,%forward)); + %p2.setRotation(FullRot(VectorScale(%up,-1),%forward)); + %p1.schedule(5000,"delete"); + %p2.schedule(5000,"delete"); + } + else if (%station.getDatablock().getName() $= "DeployableVehiclePad2") + { + %station.playThread($ActivateThread,"activate"); + %up = realvec(%station,"0 0 1"); + %forward = realvec(%station,"1 0 0"); + %p1 = CreateEmitter(%ppos,DVPADE); + %p2 = CreateEmitter(%ppos,DVPADE); + %p1.setRotation(FullRot(%up,%forward)); + %p2.setRotation(FullRot(VectorScale(%up,-1),%forward)); + %p1.schedule(5000,"delete"); + %p2.schedule(5000,"delete"); + } + else + { + %station.playThread($ActivateThread,"activate2"); + // play the FX + %fx = new StationFXVehicle() + { + dataBlock = VehicleInvFX; + stationObject = %station; + }; + } +//[[CHANGE]]!! If player is telebuying.. put him incontrol... + if ( (%client.isVehicleTeleportEnabled()) && (!%client.telebuy)) + %obj.getDataBlock().schedule(5000, "mountDriver", %obj, %client.player); + else + { + if(%obj.getDataBlock().canControl) + { + //serverCmdResetControlObject(%client); + %client.setControlObject(%obj); + commandToClient(%client, 'ControlObjectResponse', true, getControlObjectType(%obj,%client.player)); + %obj.clientControl = %client; + } + } +//[[End CHANGE]] + } + if(%obj.getTarget() != -1) + setTargetSensorGroup(%obj.getTarget(), %client.getSensorGroup()); + // We are now closing the vehicle hud when you buy a vehicle, making the following call + // unnecessary (and it breaks stuff, too!) + //VehicleHud.updateHud(%client, 'vehicleHud'); +} + +//------------------------------------------------------------------------------ +function VehicleData::mountDriver(%data, %obj, %player) +{ + if(isObject(%obj) && %obj.getDamageState() !$= "Destroyed") + { + %player.startFade(1000, 0, true); + schedule(1000, 0, "testVehicleForMount", %player, %obj); + %player.schedule(1500,"startFade",1000, 0, false); + } +} + +function testVehicleForMount(%player, %obj) +{ + if(isObject(%obj) && %obj.getDamageState() !$= "Destroyed") + %player.getDataBlock().onCollision(%player, %obj, 0); +} + + +//------------------------------------------------------------------------------ +function VehicleData::checkIfPlayersMounted(%data, %obj) +{ + for(%i = 0; %i < %obj.getDatablock().numMountPoints; %i++) + if (%obj.getMountNodeObject(%i)) + return true; + return false; +} + +//------------------------------------------------------------------------------ +function VehicleData::isMountable(%data, %obj, %val) +{ + %obj.mountable = %val; +} + +//------------------------------------------------------------------------------ +function vehicleCheck(%blockName, %team) +{ + if(($VehicleMax[%blockName] - $VehicleTotalCount[%team, %blockName]) > 0) + return true; +// else +// { +// for(%i = 0; %i < $VehicleMax[%blockName]; %i++) +// { +// %obj = $VehicleInField[%blockName, %i]; +// if(%obj.abandon) +// { +// vehicleListRemove(%blockName, %obj); +// %obj.delete(); +// return true; +// } +// } +// } + return false; +} + +//------------------------------------------------------------------------------ +function VehicleHud::updateHud( %obj, %client, %tag ) { + %client.vehInvTag = %tag; + %client.vehInvPage = ""; + if (%client.usedVehHud != 1) { + bottomPrint(%client, "(cycle weapons to view more vehicles)", 5, 1); + %client.usedVehHud = 1; + } + cycleVehicleHud(%obj, %client); +} + +//------------------------------------------------------------------------------ +function cycleVehicleHud(%obj, %client,%data) { + %tag = %client.vehInvTag; + %page = %client.vehInvPage; + if (%page $= "") + %page = 0; + else { + if (%data $= "prev") + %page--; + else + %page++; + } + %count = %client.player.station.lastCount; + VehicleHud::clearHud( %obj, %client, %tag, %count ); + %station = %client.player.station; + %team = %client.getSensorGroup(); + %count = 0; + %i = 0; + + if ( %station.vehicle[scoutVehicle] ) { + %vehicleSet[scoutVehicle] = %i; + %i++; + } + if ( %station.vehicle[AssaultVehicle] ) { + %vehicleSet[AssaultVehicle] = %i; + %i++; + } + if ( %station.vehicle[mobileBaseVehicle] ) { + %vehicleSet[mobileBaseVehicle] = %i; + %i++; + } + if ( %station.vehicle[scoutFlyer] ) { + %vehicleSet[scoutFlyer] = %i; + %i++; + } + if ( %station.vehicle[bomberFlyer] ) { + %vehicleSet[bomberFlyer] = %i; + %i++; + } + if ( %station.vehicle[hapcFlyer] ) { + %vehicleSet[hapcFlyer] = %i; + %i++; + } + if ( %station.vehicle[SuperScoutVehicle] && $Host::Purebuild == 1) { + %vehicleSet[SuperScoutVehicle] = %i; + %i++; + } + if ( %station.vehicle[SuperHAPCFlyer] && $Host::Purebuild == 1) { + %vehicleSet[SuperHAPCFlyer] = %i; + %i++; + } + if ( %station.vehicle[Artillery] ) { + %vehicleSet[Artillery] = %i; + %i++; + } + + %totalPages = mCeil(%i / 6) - 1; + if (%page < 0) + %page = %totalPages; + if (%page > %totalPages) + %page = 0; + %initPos = (%page * 6); + %endPos = %initPos + 5; + + if ( checkVehSet(%vehicleSet[scoutVehicle], %initPos)) { + messageClient( %client, 'SetLineHud', "", %tag, %count, "GRAV CYCLE", "", ScoutVehicle, $VehicleMax[ScoutVehicle] - $VehicleTotalCount[%team, ScoutVehicle] ); + %count++; + } + if ( checkVehSet(%vehicleSet[AssaultVehicle], %initPos)) { + messageClient( %client, 'SetLineHud', "", %tag, %count, "ASSAULT TANK", "", AssaultVehicle, $VehicleMax[AssaultVehicle] - $VehicleTotalCount[%team, AssaultVehicle] ); + %count++; + } + if ( checkVehSet(%vehicleSet[mobileBaseVehicle], %initPos)) { + messageClient( %client, 'SetLineHud', "", %tag, %count, "MOBILE POINT BASE", "", MobileBaseVehicle, $VehicleMax[MobileBaseVehicle] - $VehicleTotalCount[%team, MobileBaseVehicle] ); + %count++; + } + if ( checkVehSet(%vehicleSet[scoutFlyer], %initPos)) { + messageClient( %client, 'SetLineHud', "", %tag, %count, "SCOUT FLIER", "", ScoutFlyer, $VehicleMax[ScoutFlyer] - $VehicleTotalCount[%team, ScoutFlyer] ); + %count++; + } + if ( checkVehSet(%vehicleSet[bomberFlyer], %initPos)) { + messageClient( %client, 'SetLineHud', "", %tag, %count, "BOMBER", "", BomberFlyer, $VehicleMax[BomberFlyer] - $VehicleTotalCount[%team, BomberFlyer] ); + %count++; + } + if ( checkVehSet(%vehicleSet[hapcFlyer], %initPos)) { + messageClient( %client, 'SetLineHud', "", %tag, %count, "TRANSPORT", "", HAPCFlyer, $VehicleMax[HAPCFlyer] - $VehicleTotalCount[%team, HAPCFlyer] ); + %count++; + } + if ( checkVehSet(%vehicleSet[SuperScoutVehicle], %initPos)) { + messageClient( %client, 'SetLineHud', "", %tag, %count, "SUPER GRAV CYCLE", "", SuperScoutVehicle, $VehicleMax[SuperScoutVehicle] - $VehicleTotalCount[%team, SuperScoutVehicle] ); + %count++; + } + if ( checkVehSet(%vehicleSet[SuperHAPCFlyer], %initPos)) { + messageClient( %client, 'SetLineHud', "", %tag, %count, "SUPER TRANSPORT", "", SuperHAPCFlyer, $VehicleMax[SuperHAPCFlyer] - $VehicleTotalCount[%team, SuperHAPCFlyer] ); + %count++; + } + if ( checkVehSet(%vehicleSet[Artillery], %initPos)) { + messageClient( %client, 'SetLineHud', "", %tag, %count, "LONG RANGE ARTILLERY", "", Artillery, $VehicleMax[Artillery] - $VehicleTotalCount[%team, Artillery] ); + %count++; + } + + %station.lastCount = %count; + %client.vehInvPage = %page; +} + +//------------------------------------------------------------------------------ +function VehicleHud::clearHud( %obj, %client, %tag, %count ) { + for ( %i = 0; %i < %count; %i++ ) + messageClient( %client, 'RemoveLineHud', "", %tag, %i ); +} + +//------------------------------------------------------------------------------ +function checkVehSet(%obj, %initpos) { + if ((%obj !$= "") && (%obj >= %initpos) && (%obj <= (%initpos + 5))) + return true; + else + return false; +} + +//------------------------------------------------------------------------------ +function serverCmdEnableVehicleTeleport( %client, %enabled ) +{ + %client.setVehicleTeleportEnabled( %enabled ); +} diff --git a/scripts/vehicles/vehicle.cs b/scripts/vehicles/vehicle.cs new file mode 100644 index 0000000..afd8a62 --- /dev/null +++ b/scripts/vehicles/vehicle.cs @@ -0,0 +1,2131 @@ +// Notes: +// - respawning vehicles with turrets (bomber/tank) will not setup the turret properly + +//Damage Rate for entering Liquid +$VehicleDamageLava = 0.0325; +$VehicleDamageHotLava = 0.0325; +$VehicleDamageCrustyLava = 0.0325; + +$NumVehiclesDeploy = 0; + +//************************************************************** +//* GENERAL PURPOSE FUNCTIONS +//************************************************************** + + +function serverCmdFoldWings(%client) +{ + if (!isObject(%client.player)) + return; + + %veh = %client.player.getObjectMount(); + if (!isObject(%veh)) + { + return; + } + + %veh.setThreadDir($activatethread, false); + %veh.playThread($activatethread, "activate"); +} + +function serverCmdUnFoldWings(%client) +{ + if (!isObject(%client.player)) + return; + + %veh = %client.player.getObjectMount(); + if (!isObject(%veh)) + { + return; + } + + %veh.setThreadDir($activatethread, true); + %veh.playThread($activatethread, "activate"); +} + + + +function VehicleData::onAdd(%data, %obj) { + $VehicleList = listAdd($VehicleList,%obj,-1); + Parent::onAdd(%data, %obj); + if ((%data.sensorData !$= "") && (%obj.getTarget() != -1)) + setTargetSensorData(%obj.getTarget(), %data.sensorData); + %obj.setRechargeRate(%data.rechargeRate); + // set full energy + %obj.setEnergyLevel(%data.MaxEnergy); + + if (%obj.disableMove) + %obj.immobilized = true; + if (%obj.deployed) + { + if ($countDownStarted) + %data.schedule(($Host::WarmupTime * 1000) / 2, "vehicleDeploy", %obj, 0, 1); + else + { + $VehiclesDeploy[$NumVehiclesDeploy] = %obj; + $NumVehiclesDeploy++; + } + } + if (%obj.mountable || %obj.mountable $= "") + %data.isMountable(%obj, true); + else + %data.isMountable(%obj, false); + + %obj.setSelfPowered(); +// %data.canObserve = true; +} + +function VehicleData::onRemove(%this, %obj) +{ + // if there are passengers/driver, kick them out + %this.deleteAllMounted(%obj); + +//[[CHANGE]] Kick commander out as well + if (%obj.clientControl) + serverCmdResetControlObject(%obj.clientControl); + + + for(%i = 0; %i < %obj.getDatablock().numMountPoints; %i++) + if (%obj.getMountNodeObject(%i)) { + %passenger = %obj.getMountNodeObject(%i); + %passenger.unmount(); + } + vehicleListRemove(%obj.getDataBlock(), %obj); + if (%obj.lastPilot.lastVehicle == %obj) + %obj.lastPilot.lastVehicle = ""; + + %loc = findWord($VehicleList,%obj); + if (%loc !$= "") + $VehicleList = listDel($VehicleList,%loc); + + //[most] yah.. nukes can now be removed :D + if (%obj.nuke !$= "") + { + %obj.nuke.mpm_all_off(1); + %obj.unmountObject(%obj.nuke); + %obj.nuke.schedule(1500,"delete"); + } + //[most] + + Parent::onRemove(%this, %obj); +} + +function VehicleData::onDamage(%this,%obj) +{ + %damage = %obj.getDamageLevel(); + if (%damage >= %this.destroyedLevel) + { + if (%obj.getDamageState() !$= "Destroyed") + { + if (%obj.respawnTime !$= "") + %obj.marker.schedule = %obj.marker.data.schedule(%obj.respawnTime, "respawn", %obj.marker); + %obj.setDamageState(Destroyed); + } + } + else + { + if (%obj.getDamageState() !$= "Enabled") + %obj.setDamageState(Enabled); + } +} + +function VehicleData::playerDismounted(%data, %obj, %player) +{ + if ( %player.client.observeCount > 0 ) + resetObserveFollow( %player.client, true ); + + setTargetSensorGroup(%obj.getTarget(), %obj.team); + + // if there is a turret, set its team as well. + if ( %obj.turretObject > 0 ) + setTargetSensorGroup(%obj.turretObject.getTarget(), %obj.team); +} + +function HoverVehicle::useCreateHeight() +{ + //this function is declared to prevent console error msg spam... +} + +function WheeledVehicle::useCreateHeight() +{ + //this function is declared to prevent console error msg spam... +} + +function AssaultVehicle::onDamage(%this, %obj) +{ + if (isObject(%obj.getMountNodeObject(10))) + (%obj.getMountNodeObject(10)).setDamagelevel(%obj.getDamageLevel()); + Parent::onDamage(%this, %obj); +} + +function BomberFlyer::onDamage(%this, %obj) +{ + if (isObject(%obj.getMountNodeObject(10))) + (%obj.getMountNodeObject(10)).setDamagelevel(%obj.getDamageLevel()); + Parent::onDamage(%this, %obj); +} + +function MobileBaseVehicle::onDamage(%this, %obj) +{ + if (isObject(%obj.getMountNodeObject(1))) + (%obj.getMountNodeObject(1)).setDamagelevel(%obj.getDamageLevel()); + Parent::onDamage(%this, %obj); +} + +function VehicleData::onEnterLiquid(%data, %obj, %coverage, %type) +{ + switch(%type) + { + case 0: + //Water + %obj.setHeat(0.0); + case 1: + //Ocean Water + %obj.setHeat(0.0); + case 2: + //River Water + %obj.setHeat(0.0); + case 3: + //Stagnant Water + %obj.setHeat(0.0); + case 4: + //Lava + %obj.liquidDamage(%data, $VehicleDamageLava, $DamageType::Lava); + case 5: + //Hot Lava + %obj.liquidDamage(%data, $VehicleDamageHotLava, $DamageType::Lava); + case 6: + //Crusty Lava + %obj.liquidDamage(%data, $VehicleDamageCrustyLava, $DamageType::Lava); + case 7: + //Quick Sand + } +} + +function FlyingVehicle::liquidDamage(%obj, %data, %damageAmount, %damageType) +{ + if (%obj.getDamageState() !$= "Destroyed") + { + %data.damageObject(%obj, 0, "0 0 0", %damageAmount, %damageType); + %obj.lDamageSchedule = %obj.schedule(50, "liquidDamage", %data, %damageAmount, %damageType); + passengerLiquidDamage(%obj, %damageAmount, %damageType); + } + else + %obj.lDamageSchedule = ""; +} + +function WheeledVehicle::liquidDamage(%obj, %data, %damageAmount, %damageType) +{ + if (%obj.getDamageState() !$= "Destroyed") + { + %data.damageObject(%obj, 0, "0 0 0", %damageAmount, %damageType); + %obj.lDamageSchedule = %obj.schedule(50, "liquidDamage", %data, %damageAmount, %damageType); + passengerLiquidDamage(%obj, %damageAmount, %damageType); + } + else + %obj.lDamageSchedule = ""; +} + +function HoverVehicle::liquidDamage(%obj, %data, %damageAmount, %damageType) +{ + if (%obj.getDamageState() !$= "Destroyed") + { + %data.damageObject(%obj, 0, "0 0 0", %damageAmount, %damageType); + %obj.lDamageSchedule = %obj.schedule(50, "liquidDamage", %data, %damageAmount, %damageType); + passengerLiquidDamage(%obj, %damageAmount, %damageType); + } + else + %obj.lDamageSchedule = ""; +} + +function passengerLiquidDamage(%obj, %damageAmount, %damageType) +{ +// for(%i = %num; %i < %obj.getDataBlock().numMountPoints; %i++) +// if (%p = %obj.getMountNodeObject(%i)) +// %p.liquidDamage(%p.getDatablock(), $DamageLava, $DamageType::Lava); +} + +function VehicleData::onLeaveLiquid(%data, %obj, %type) +{ + switch(%type) + { + case 0: + //Water + %obj.setHeat(1.0); + case 1: + //Ocean Water + %obj.setHeat(1.0); + case 2: + //River Water + %obj.setHeat(1.0); + case 3: + //Stagnant Water + %obj.setHeat(1.0); + case 4: + //Lava + case 5: + //Hot Lava + case 6: + //Crusty Lava + case 7: + //Quick Sand + } + + if (%obj.lDamageSchedule !$= "") + { + cancel(%obj.lDamageSchedule); + %obj.lDamageSchedule = ""; + } +} + +function VehicleData::onDestroyed(%data, %obj, %prevState) { + // TODO - temporary - remove + if ($VehicleDestroyedOverride == 1) { + %obj.setDamageLevel(0); + %obj.setDamageState(Enabled); + return; + } + if (%obj.lastDamagedBy) + { + %destroyer = %obj.lastDamagedBy; + game.vehicleDestroyed(%obj, %destroyer); + //error("vehicleDestroyed( "@ %obj @", "@ %destroyer @")"); + } + + radiusVehicleExplosion(%data, %obj); + if (%obj.turretObject) + if (%obj.turretObject.getControllingClient()) + %obj.turretObject.getDataBlock().playerDismount(%obj.turretObject); + for(%i = 0; %i < %obj.getDatablock().numMountPoints; %i++) + { + if (%obj.getMountNodeObject(%i)) { + %flingee = %obj.getMountNodeObject(%i); + %flingee.getDataBlock().doDismount(%flingee, true); + %xVel = 250.0 - (getRandom() * 500.0); + %yVel = 250.0 - (getRandom() * 500.0); + %zVel = (getRandom() * 100.0) + 50.0; + %flingVel = %xVel @ " " @ %yVel @ " " @ %zVel; + %flingee.applyImpulse(%flingee.getTransform(), %flingVel); + %flingee.damage(0, %obj.getPosition(), 0.4, $DamageType::Crash); + } + } +//[[CHANGE]] + if (%obj.clientControl) + serverCmdResetControlObject(%obj.clientControl); + + %data.deleteAllMounted(%obj); + + // --------------------------------------------------------------------------------- + // z0dd - ZOD - Czar, 6/24/02. Move this vehicle out of the way so nothing collides + // with it. + if (%data.getName() $= "BomberFlyer" || %data.getName() $= "MobileBaseVehicle" || %data.getName() $= "AssaultVehicle") + { + %obj.setFrozenState(true); + %obj.schedule(2000, "delete"); + %data.schedule(500, 'onAvoidCollisions', %obj); + } + else + { + %obj.setFrozenState(true); + %obj.schedule(500, "delete"); + } + // --------------------------------------------------------------------------------- +} + +// ---------------------------------------------------------------------------------- +// z0dd - ZOD, 6/13/02. Move this vehicle out of the way so nothing collides with it. +function VehicleData::onAvoidCollisions(%data, %obj) +{ + + // Get the current location of the vehicle and send it to the moon! + %transform = posFromTransform(%obj.getTransform()); + %position = getWord(%transform, 0) SPC getWord(%transform, 1) SPC (getWord(%transform, 2) - 20000); + %rotation = getWord(%transform, 3) SPC getWord(%transform, 4) SPC getWord(%transform, 5) SPC getWord(%transform, 6); + %obj.setTransform(%position SPC %rotation); +} +// ---------------------------------------------------------------------------------- + +function radiusVehicleExplosion(%data, %vehicle) +{ + // this is a modified version of RadiusExplosion() from projectiles.cs + %position = %vehicle.getPosition(); + InitContainerRadiusSearch(%position, %data.explosionRadius, $TypeMasks::PlayerObjectType | + $TypeMasks::VehicleObjectType | + $TypeMasks::MoveableObjectType | + $TypeMasks::StaticShapeObjectType | + $TypeMasks::ForceFieldObjectType | + $TypeMasks::TurretObjectType | + $TypeMasks::ItemObjectType); + + %numTargets = 0; + while ((%targetObject = containerSearchNext()) != 0) + { + if (%targetObject == %vehicle) + continue; + + %dist = containerSearchCurrRadDamageDist(); + + if (%dist > %data.explosionRadius) + continue; + + if (!%targetObject.isforcefield() && %targetObject.isMounted()) + { + %mount = %targetObject.getObjectMount(); + if (%mount == %vehicle) + continue; + + %found = -1; + for (%i = 0; %i < %mount.getDataBlock().numMountPoints; %i++) + { + if (%mount.getMountNodeObject(%i) == %targetObject) + { + %found = %i; + break; + } + } + + if (%found != -1) + { + if (%mount.getDataBlock().isProtectedMountPoint[%found] && (%mount != %vehicle)) + continue; + } + } + + %targets[%numTargets] = %targetObject; + %targetDists[%numTargets] = %dist; + %numTargets++; + } + + for (%i = 0; %i < %numTargets; %i++) + { + %targetObject = %targets[%i]; + %dist = %targetDists[%i]; + + %coverage = calcExplosionCoverage(%position, %targetObject, + ($TypeMasks::InteriorObjectType | + $TypeMasks::TerrainObjectType | + $TypeMasks::ForceFieldObjectType)); + if (%coverage == 0) + continue; + + %amount = (1.0 - (%dist / %data.explosionRadius)) * %coverage * %data.explosionDamage; + %targetData = %targetObject.getDataBlock(); + + %momVec = "0 0 1"; + + if (%amount > 0) + %targetData.damageObject(%targetObject, %sourceObject, %position, %amount, $DamageType::Explosion, %momVec); + } +} + +function VehicleData::deleteAllMounted() +{ + +} + +//************************************************************** +//* VEHICLE CREATION +//************************************************************** +// (NOTE: No entry for Wildcat Grav Cycle is here. -- DG) + +//---------------------------- +// SHRIKE SCOUT FLIER +//---------------------------- + +function ScoutFlyer::onAdd(%this, %obj) +{ + Parent::onAdd(%this, %obj); +//[[CHANGE]] + if (%obj.clientControl) + serverCmdResetControlObject(%obj.clientControl); + + + %obj.mountImage(ScoutChaingunParam, 0); + %obj.mountImage(ScoutChaingunImage, 2); + %obj.mountImage(ScoutChaingunPairImage, 3); + %obj.nextWeaponFire = 2; + %obj.schedule(5500, "playThread", $ActivateThread, "activate"); +} + +//---------------------------- +// THUNDERSWORD BOMBER +//---------------------------- + +function BomberFlyer::onAdd(%this, %obj) +{ + Parent::onAdd(%this, %obj); + + %turret = TurretData::create(BomberTurret); + MissionCleanup.add(%turret); + %turret.team = %obj.teamBought; + %turret.selectedWeapon = 1; + %turret.setSelfPowered(); + %obj.mountObject(%turret, 10); + %turret.mountImage(BomberTurretBarrel,2); + %turret.mountImage(BomberTurretBarrelPair,3); + %turret.mountImage(BomberBombImage, 4); + %turret.mountImage(BomberBombPairImage, 5); + %turret.mountImage(BomberTargetingImage, 6); + %obj.turretObject = %turret; + %turret.setCapacitorRechargeRate( %turret.getDataBlock().capacitorRechargeRate ); + %turret.vehicleMounted = %obj; + + //vehicle turrets should not auto fire at targets + %turret.setAutoFire(false); + + //for this particular weapon - a non-firing datablock used only so the AI can aim the turret + //Also needed so we can set the turret parameters.. + %turret.mountImage(AIAimingTurretBarrel, 0); + + // setup the turret's target info + setTargetSensorGroup(%turret.getTarget(), %turret.team); + setTargetNeverVisMask(%turret.getTarget(), 0xffffffff); +} + +//---------------------------- +// HAVOC TRANSPORT FLIER +//---------------------------- + +function HAPCFlyer::onAdd(%this, %obj) +{ + Parent::onAdd(%this, %obj); + %obj.schedule(6000, "playThread", $ActivateThread, "activate"); +} + +//---------------------------- +// SUPER HAVOC TRANSPORT FLIER +//---------------------------- + +function SuperHAPCFlyer::onAdd(%this, %obj) { + Parent::onAdd(%this, %obj); + %obj.schedule(6000, "playThread", $ActivateThread, "activate"); +} + +//---------------------------- +// BEOWULF ASSAULT VEHICLE +//---------------------------- + +function AssaultVehicle::onAdd(%this, %obj) +{ + Parent::onAdd(%this, %obj); + + %turret = TurretData::create(AssaultPlasmaTurret); + %turret.selectedWeapon = 1; + MissionCleanup.add(%turret); + %turret.team = %obj.teamBought; + %turret.setSelfPowered(); + %obj.mountObject(%turret, 10); + %turret.mountImage(AssaultPlasmaTurretBarrel, 2); + %turret.mountImage(AssaultMortarTurretBarrel, 4); + %turret.setCapacitorRechargeRate( %turret.getDataBlock().capacitorRechargeRate ); + %obj.turretObject = %turret; + + //vehicle turrets should not auto fire at targets + %turret.setAutoFire(false); + + //Needed so we can set the turret parameters.. + %turret.mountImage(AssaultTurretParam, 0); + %obj.schedule(6000, "playThread", $ActivateThread, "activate"); + + // set the turret's target info + setTargetSensorGroup(%turret.getTarget(), %turret.team); + setTargetNeverVisMask(%turret.getTarget(), 0xffffffff); +} + +//---------------------------- +// JERICHO FORWARD BASE (Mobile Point Base) +//---------------------------- + +function MobileBaseVehicle::onAdd(%this, %obj) +{ + Parent::onAdd(%this, %obj); + %obj.station = ""; + %obj.turret = ""; + %obj.beacon = ""; + + %obj.schedule(5000, "playThread", $AmbientThread, "ambient"); +} + +function KillerMobileBaseVehicle::onAdd(%this, %obj) +{ + Parent::onAdd(%this, %obj); + %obj.station = ""; + %obj.turret = ""; + %obj.beacon = ""; + + %obj.schedule(5000, "playThread", $AmbientThread, "ambient"); +} +//************************************************************** +//* MULTI-CREW VEHICLE DELETION +//************************************************************** + +//---------------------------- +//BEOWULF ASSAULT VEHICLE +//---------------------------- + +function AssaultVehicle::deleteAllMounted(%data, %obj) +{ + %turret = %obj.getMountNodeObject(10); + if (!%turret) + return; + + if (%client = %turret.getControllingClient()) + { + %client.player.setControlObject(%client.player); + %client.player.mountImage(%client.player.lastWeapon, $WeaponSlot); + %client.player.mountVehicle = false; + } + %turret.schedule(2000, delete); +} + +//---------------------------- +// THUNDERSWORD BOMBER +//---------------------------- + +function BomberFlyer::deleteAllMounted(%data, %obj) +{ + if (isObject(%obj.beacon)) + %obj.beacon.schedule(50, delete); + + %turret = %obj.getMountNodeObject(10); + if (!%turret) + return; + + %turret.altTrigger = 0; + %turret.fireTrigger = 0; + + if (%client = %turret.getControllingClient()) + { + commandToClient(%client, 'endBomberSight'); + %client.player.setControlObject(%client.player); + %client.player.mountImage(%client.player.lastWeapon, $WeaponSlot); + %client.player.mountVehicle = false; + + %client.player.bomber = false; + %client.player.isBomber = false; + } + %turret.schedule(2000, delete); +} + +//---------------------------- +// JERICHO FORWARD BASE +//---------------------------- + +function MobileBaseVehicle::deleteAllMounted(%data, %obj) +{ + if (%obj.station !$= "") + { + %obj.station.getDataBlock().onLosePowerDisabled(%obj.station); + %obj.unmountObject(%obj.station); + %obj.station.trigger.schedule(2000, delete); + %obj.station.schedule(2000, delete); + } + if (%obj.turret !$= "") + { + %obj.turret.getDataBlock().onLosePowerDisabled(%obj.turret); + %obj.unmountObject(%obj.turret); + %obj.turret.schedule(2000, delete); + } + //[most] + if (%obj.nuke !$= "") + { + %obj.nuke.mpm_all_off(1); + %obj.unmountObject(%obj.nuke); + %obj.nuke.schedule(1500,"delete"); + } + //[most] + if (isObject(%obj.shield)) + %obj.shield.schedule(2000, delete); + + if (isObject(%obj.beacon)) + { + %obj.beacon.schedule(0, delete); + } +} +function KillerMobileBaseVehicle::deleteAllMounted(%data, %obj) +{ + if (%obj.station !$= "") + { + %obj.station.getDataBlock().onLosePowerDisabled(%obj.station); + %obj.unmountObject(%obj.station); + %obj.station.trigger.schedule(2000, delete); + %obj.station.schedule(2000, delete); + } + if (%obj.turret !$= "") + { + %obj.turret.getDataBlock().onLosePowerDisabled(%obj.turret); + %obj.unmountObject(%obj.turret); + %obj.turret.schedule(2000, delete); + } + //[most] + if (%obj.nuke !$= "") + { + %obj.nuke.mpm_all_off(1); + %obj.unmountObject(%obj.nuke); + %obj.nuke.schedule(1500,"delete"); + } + //[most] + if (isObject(%obj.shield)) + %obj.shield.schedule(2000, delete); + + if (isObject(%obj.beacon)) + { + %obj.beacon.schedule(0, delete); + } +} +//************************************************************** +//* WEAPON MOUNTING ON VEHICLES +//************************************************************** + +//---------------------------- +// SHRIKE SCOUT FLIER +//---------------------------- + +function ScoutFlyer::playerMounted(%data, %obj, %player, %node) +{ +//[[CHANGE]] + if (%obj.clientControl) + serverCmdResetControlObject(%obj.clientControl); + + // scout flyer == SUV (single-user vehicle) + commandToClient(%player.client, 'setHudMode', 'Pilot', "Shrike", %node); + $numVWeapons = 1; + + // update observers who are following this guy... + if ( %player.client.observeCount > 0 ) + resetObserveFollow( %player.client, false ); +} + +//---------------------------- +// THUNDERSWORD BOMBER +//---------------------------- + +function BomberFlyer::playerMounted(%data, %obj, %player, %node) +{ +//[[CHANGE]] + if (%obj.clientControl) + serverCmdResetControlObject(%obj.clientControl); + + if (%node == 0) + { + // pilot position + %player.setPilot(true); + commandToClient(%player.client, 'setHudMode', 'Pilot', "Bomber", %node); + } + else if (%node == 1) + { + // bombardier position + %turret = %obj.getMountNodeObject(10); + %player.vehicleTurret = %turret; + %player.setTransform("0 0 0 0 0 1 0"); + %player.lastWeapon = %player.getMountedImage($WeaponSlot); + %player.unmountImage($WeaponSlot); + if (!%player.client.isAIControlled()) + { + %player.setControlObject(%turret); + %player.client.setObjectActiveImage(%turret, 2); + } + commandToClient(%player.client, 'startBomberSight'); + %turret.bomber = %player; + $bWeaponActive = 0; + %obj.getMountNodeObject(10).selectedWeapon = 1; + commandToClient(%player.client,'SetWeaponryVehicleKeys', true); + + commandToClient(%player.client, 'setHudMode', 'Pilot', "Bomber", %node); + %player.isBomber = true; + } + else + { + // tail gunner position + commandToClient(%player.client, 'setHudMode', 'Passenger', "Bomber", %node); + } + // build a space-separated string representing passengers + // 0 = no passenger; 1 = passenger (e.g. "1 0 0 ") + %passString = buildPassengerString(%obj); + // send the string of passengers to all mounted players + for(%i = 0; %i < %data.numMountPoints; %i++) + if (%obj.getMountNodeObject(%i) > 0) + commandToClient(%obj.getMountNodeObject(%i).client, 'checkPassengers', %passString); + + // update observers who are following this guy... + if ( %player.client.observeCount > 0 ) + resetObserveFollow( %player.client, false ); +} + +//---------------------------- +// HAVOC TRANSPORT FLIER +//---------------------------- + +function HAPCFlyer::playerMounted(%data, %obj, %player, %node) +{ +//[[CHANGE]] + if (%obj.clientControl) + serverCmdResetControlObject(%obj.clientControl); + + if (%node == 0) { + // pilot position + commandToClient(%player.client, 'setHudMode', 'Pilot', "HAPC", %node); + } + else { + // all others + commandToClient(%player.client, 'setHudMode', 'Passenger', "HAPC", %node); + } + // build a space-separated string representing passengers + // 0 = no passenger; 1 = passenger (e.g. "1 0 0 1 1 0 ") + %passString = buildPassengerString(%obj); + // send the string of passengers to all mounted players + for(%i = 0; %i < %data.numMountPoints; %i++) + if (%obj.getMountNodeObject(%i) > 0) + commandToClient(%obj.getMountNodeObject(%i).client, 'checkPassengers', %passString); + + // update observers who are following this guy... + if ( %player.client.observeCount > 0 ) + resetObserveFollow( %player.client, false ); +} + +//---------------------------- +// SUPER HAVOC TRANSPORT FLIER +//---------------------------- + +function SuperHAPCFlyer::playerMounted(%data, %obj, %player, %node) { + // [[CHANGE]] + if (%obj.clientControl) + serverCmdResetControlObject(%obj.clientControl); + + if (%node == 0) { + // pilot position + commandToClient(%player.client, 'setHudMode', 'Pilot', "HAPC", %node); + } + else { + // all others + commandToClient(%player.client, 'setHudMode', 'Passenger', "HAPC", %node); + } + // build a space-separated string representing passengers + // 0 = no passenger; 1 = passenger (e.g. "1 0 0 1 1 0 ") + %passString = buildPassengerString(%obj); + // send the string of passengers to all mounted players + for(%i = 0; %i < %data.numMountPoints; %i++) + if (%obj.getMountNodeObject(%i) > 0) + commandToClient(%obj.getMountNodeObject(%i).client, 'checkPassengers', %passString); + + // update observers who are following this guy... + if ( %player.client.observeCount > 0 ) + resetObserveFollow( %player.client, false ); +} + +//---------------------------- +// WILDCAT GRAV CYCLE +//---------------------------- + +function ScoutVehicle::playerMounted(%data, %obj, %player, %node) +{ +//[[CHANGE]] + if (%obj.clientControl) + serverCmdResetControlObject(%obj.clientControl); + + // scout vehicle == SUV (single-user vehicle) + commandToClient(%player.client, 'setHudMode', 'Pilot', "Hoverbike", %node); + + // update observers who are following this guy... + if ( %player.client.observeCount > 0 ) + resetObserveFollow( %player.client, false ); +} + +//---------------------------- +// SUPER WILDCAT GRAV CYCLE +//---------------------------- + +function SuperScoutVehicle::playerMounted(%data, %obj, %player, %node) { + // [[CHANGE]] + if (%obj.clientControl) + serverCmdResetControlObject(%obj.clientControl); + + // scout vehicle == SUV (single-user vehicle) + commandToClient(%player.client, 'setHudMode', 'Pilot', "Hoverbike", %node); + + // update observers who are following this guy... + if ( %player.client.observeCount > 0 ) + resetObserveFollow( %player.client, false ); +} + +//---------------------------- +// BEOWULF ASSAULT VEHICLE +//---------------------------- + +function AssaultVehicle::playerMounted(%data, %obj, %player, %node) +{ +//[[CHANGE]] + if (%obj.clientControl) + serverCmdResetControlObject(%obj.clientControl); + + if (%node == 0) { + // driver position + // is there someone manning the turret? + //%turreteer = %obj.getMountedNodeObject(1); + commandToClient(%player.client, 'setHudMode', 'Pilot', "Assault", %node); + } + else if (%node == 1) + { + // turreteer position + %turret = %obj.getMountNodeObject(10); + %player.vehicleTurret = %turret; + %player.setTransform("0 0 0 0 0 1 0"); + %player.lastWeapon = %player.getMountedImage($WeaponSlot); + %player.unmountImage($WeaponSlot); + if (!%player.client.isAIControlled()) + { + %player.setControlObject(%turret); + %player.client.setObjectActiveImage(%turret, 2); + } + %turret.turreteer = %player; + // if the player is the turreteer, show vehicle's weapon icons + //commandToClient(%player.client, 'showVehicleWeapons', %data.getName()); + //%player.client.setVWeaponsHudActive(1); // plasma turret icon (default) + + $aWeaponActive = 0; + commandToClient(%player.client,'SetWeaponryVehicleKeys', true); + %obj.getMountNodeObject(10).selectedWeapon = 1; + commandToClient(%player.client, 'setHudMode', 'Pilot', "Assault", %node); + } + + // update observers who are following this guy... + if ( %player.client.observeCount > 0 ) + resetObserveFollow( %player.client, false ); + + // build a space-separated string representing passengers + // 0 = no passenger; 1 = passenger (e.g. "1 0 ") + %passString = buildPassengerString(%obj); + // send the string of passengers to all mounted players + for(%i = 0; %i < %data.numMountPoints; %i++) + if (%obj.getMountNodeObject(%i) > 0) + commandToClient(%obj.getMountNodeObject(%i).client, 'checkPassengers', %passString); +} + +//---------------------------- +// JERICHO FORWARD BASE +//---------------------------- + +function MobileBaseVehicle::playerMounted(%data, %obj, %player, %node) +{ +//[[CHANGE]] + if (%obj.clientControl) + serverCmdResetControlObject(%obj.clientControl); + + // MPB vehicle == SUV (single-user vehicle) + commandToClient(%player.client, 'setHudMode', 'Pilot', "MPB", %node); + if (%obj.deploySchedule) + { + %obj.deploySchedule.clear(); + %obj.deploySchedule = ""; + } + + if (%obj.deployed !$= "" && %obj.deployed == 1) + { + %obj.setThreadDir($DeployThread, false); + %obj.playThread($DeployThread,"deploy"); + %obj.playAudio($DeploySound, MobileBaseUndeploySound); + %obj.station.setThreadDir($DeployThread, false); + %obj.station.getDataBlock().onLosePowerDisabled(%obj.station); + %obj.station.clearSelfPowered(); + %obj.station.goingOut=false; + %obj.station.notDeployed = 1; + %obj.station.playAudio($DeploySound, MobileBaseStationUndeploySound); + if (isObject(%obj.turret)) + { + if ((%turretClient = %obj.turret.getControllingClient()) !$= "") + { + CommandToServer( 'resetControlObject', %turretClient ); + } + + %obj.turret.setThreadDir($DeployThread, false); + %obj.turret.clearTarget(); + %obj.turret.setTargetObject(-1); + + %obj.turret.playAudio($DeploySound, MobileBaseTurretUndeploySound); + } + //[most] + if (isObject(%obj.nuke)) + %obj.nuke.mpm_all_off(0); + //[most] + %obj.shield.open(); + %obj.shield.schedule(1000,"delete"); + %obj.deploySchedule = ""; + + %obj.fullyDeployed = 0; + + %obj.noEnemyControl = 0; + } + %obj.deployed = 0; + + // update observers who are following this guy... + if ( %player.client.observeCount > 0 ) + resetObserveFollow( %player.client, false ); +} + +function KillerMobileBaseVehicle::playerMounted(%data, %obj, %player, %node) +{ +//[[CHANGE]] + if (%obj.clientControl) + serverCmdResetControlObject(%obj.clientControl); + + // MPB vehicle == SUV (single-user vehicle) + commandToClient(%player.client, 'setHudMode', 'Pilot', "MPB", %node); + if (%obj.deploySchedule) + { + %obj.deploySchedule.clear(); + %obj.deploySchedule = ""; + } + + if (%obj.deployed !$= "" && %obj.deployed == 1) + { + %obj.setThreadDir($DeployThread, false); + %obj.playThread($DeployThread,"deploy"); + %obj.playAudio($DeploySound, MobileBaseUndeploySound); + %obj.station.setThreadDir($DeployThread, false); + %obj.station.getDataBlock().onLosePowerDisabled(%obj.station); + %obj.station.clearSelfPowered(); + %obj.station.goingOut=false; + %obj.station.notDeployed = 1; + %obj.station.playAudio($DeploySound, MobileBaseStationUndeploySound); + if (isObject(%obj.turret)) + { + if ((%turretClient = %obj.turret.getControllingClient()) !$= "") + { + CommandToServer( 'resetControlObject', %turretClient ); + } + + %obj.turret.setThreadDir($DeployThread, false); + %obj.turret.clearTarget(); + %obj.turret.setTargetObject(-1); + + %obj.turret.playAudio($DeploySound, MobileBaseTurretUndeploySound); + } + //[most] + if (isObject(%obj.nuke)) + %obj.nuke.mpm_all_off(0); + //[most] + %obj.shield.open(); + %obj.shield.schedule(1000,"delete"); + %obj.deploySchedule = ""; + + %obj.fullyDeployed = 0; + + %obj.noEnemyControl = 0; + } + %obj.deployed = 0; + + // update observers who are following this guy... + if ( %player.client.observeCount > 0 ) + resetObserveFollow( %player.client, false ); +} + + +function buildPassengerString(%vehicle) +{ + %passStr = ""; + for(%i = 0; %i < %vehicle.getDatablock().numMountPoints; %i++) + { + if (%vehicle.getMountNodeObject(%i) > 0) + %passStr = %passStr @ "1 "; + else + %passStr = %passStr @ "0 "; + } + + return %passStr; +} + +function MobileBaseVehicle::playerDismounted(%data, %obj, %player) +{ + %obj.schedule(500, "deployVehicle", %data, %player); + Parent::playerDismounted( %data, %obj, %player ); +} + +function KillerMobileBaseVehicle::playerDismounted(%data, %obj, %player) +{ + %obj.schedule(500, "deployVehicle", %data, %player); + Parent::playerDismounted( %data, %obj, %player ); +} + +function WheeledVehicle::deployVehicle(%obj, %data, %player) +{ + if (!%data.vehicleDeploy(%obj, %player)) + %obj.schedule(500, "deployVehicle", %data, %player); +} + +//************************************************************** +//* JERICHO DEPLOYMENT and UNDEPLOYMENT +//************************************************************** + +function MobileBaseVehicle::vehicleDeploy(%data, %obj, %player, %force) +{ + + if (VectorLen(%obj.getVelocity()) <= 0.1 || %force) + { + %deployMessage = ""; + if ( (%deployMessage = %data.checkTurretDistance(%obj)) $= "" || %force) + { + if (%obj.station $= "") + { + if ( (%deployMessage = %data.checkDeploy(%obj)) $= "" || %force) + { + %obj.station = new StaticShape() { + scale = "1 1 1"; + dataBlock = "MobileInvStation"; + lockCount = "0"; + homingCount = "0"; + team = %obj.team; + vehicle = %obj; + }; + %obj.station.startFade(0,0,true); + %obj.mountObject(%obj.station, 2); + %obj.station.getDataBlock().createTrigger(%obj.station); + %obj.station.setSelfPowered(); + %obj.station.playThread($PowerThread,"Power"); + %obj.station.playAudio($HumSound,StationHumSound); + %obj.station.vehicle = %obj; + + //[most] Only give mpb's nukes when enabled in options + if ($MPM::NukeMPB) + { + %obj.nuke=%obj.Mpm_Turret(); + %obj.nuke.ammo = %obj.nukeammo; + } + else //Otherwise give normal turret. + { + %obj.turret = new turret() + { + scale = "1 1 1"; + dataBlock = "MobileTurretBase"; + lockCount = "0"; + homingCount = "0"; + team = %obj.team; + }; + %obj.turret.setDamageLevel(%obj.getDamageLevel()); + %obj.mountObject(%obj.turret, 1); + %obj.turret.setSelfPowered(); + %obj.turret.playThread($PowerThread,"Power"); + %obj.turret.mountImage(MissileBarrelLarge, 0 ,false); + } + + + %obj.beacon = new BeaconObject() { + dataBlock = "DeployedBeacon"; + position = %obj.position; + rotation = %obj.rotation; + team = %obj.team; + }; + %obj.beacon.setBeaconType(friend); + %obj.beacon.setTarget(%obj.team); + // --------------------------------- + // z0dd - ZOD, 5/8/02. Invalid call. + //checkSpawnPos(%obj, 20); + } + } + else + { + %obj.station.setSelfPowered(); + %obj.station.playThread($PowerThread,"Power"); + //[most] //check if there "is" an turret + if (isObject(%obj.turret)) + { + %obj.turret.setSelfPowered(); + %obj.turret.playThread($PowerThread,"Power"); + } + //[most] + } + if (%deployMessage $= "" || %force) + { + //[most] + if (isObject(%obj.turret)) + { + if (%obj.turret.getTarget() == -1) + { + %obj.turret.setTarget(%obj.turret.target); + } + %obj.turret.setThreadDir($DeployThread, true); + %obj.turret.playThread($DeployThread,"deploy"); + %obj.turret.playAudio($DeploySound, MobileBaseTurretDeploySound); + } + if (isObject(%obj.nuke)) + %obj.nuke.mpm_all_on(); + //[most] + %obj.station.notDeployed = 1; + %obj.setThreadDir($DeployThread, true); + %obj.playThread($DeployThread,"deploy"); + %obj.playAudio($DeploySound, MobileBaseDeploySound); + %obj.deployed = 1; + %obj.deploySchedule = ""; + %obj.disableMove = true; + %obj.setFrozenState(true); + if (isObject(%obj.shield)) + %obj.shield.delete(); + + %obj.shield = new forceFieldBare() + { + scale = "1.22 1.8 1.1"; + dataBlock = "defaultTeamSlowFieldBare"; + team = %obj.team; + }; + %obj.shield.open(); + setTargetSensorData(%obj.getTarget(), MPBDeployedSensor); + } + } + if (%deployMessage !$= "") + messageClient(%player.client, '', %deployMessage); + + return true; + } + else + { + return false; + } +} + +function MobileBaseVehicle::onEndSequence(%data, %obj, %thread) +{ + if (%thread == $DeployThread && !%obj.deployed) + { + %obj.unmountObject(%obj.station); + %obj.station.trigger.delete(); + %obj.station.delete(); + %obj.station = ""; + + %obj.beacon.delete(); + //[most] Handles removal of nuke. + if (isObject(%obj.nuke)) + { + %obj.nukeammo = %obj.nuke.ammo; + %obj.nuke.mpm_all_off(1); + %obj.unmountObject(%obj.nuke); + %obj.nuke.schedule(1500,"delete"); + } + if (isObject(%obj.turret)) + { + %obj.unmountObject(%obj.turret); + %obj.turret.delete(); + %obj.turret = ""; + } + //[most] + if (!%obj.immobilized) + { + %obj.disableMove = false; + %obj.setFrozenState(false); + } + setTargetSensorData(%obj.getTarget(), %data.sensorData); + } + else + { + %obj.station.startFade(0,0,false); + %obj.station.setThreadDir($DeployThread, true); + %obj.station.playThread($DeployThread,"deploy"); + %obj.station.playAudio($DeploySound, MobileBaseStationDeploySound); + %obj.station.goingOut = true; + %obj.shield.setTransform(%obj.getSlotTransform(3)); + %obj.shield.close(); + %obj.isDeployed = true; + %obj.noEnemyControl = 1; + } + + Parent::onEndSequence(%data, %obj, %thread); +} + +function MobileInvStation::onEndSequence(%data, %obj, %thread) +{ + if (!%obj.goingOut) + %obj.startFade(0,0,true); + else + { + %obj.notDeployed = 0; + %obj.vehicle.fullyDeployed = 1; + } + Parent::onEndSequence(%data, %obj, %thread); +} + + +function MobileBaseVehicle::checkDeploy(%data, %obj) +{ + + %mask = $TypeMasks::VehicleObjectType | $TypeMasks::MoveableObjectType | + $TypeMasks::StaticShapeObjectType | $TypeMasks::ForceFieldObjectType | + $TypeMasks::ItemObjectType | $TypeMasks::PlayerObjectType | + $TypeMasks::TurretObjectType | //$TypeMasks::StaticTSObjectType | + $TypeMasks::InteriorObjectType; + + //%slot 1 = turret %slot 2 = station + %height[1] = 0; + %height[2] = 0; + %radius[1] = 2.4; + %radius[2] = 2.4; + %stationFailed = false; + %turretFailed = false; + + for(%x = 1; %x < 3; %x++) + { + %posXY = getWords(%obj.getSlotTransform(%x), 0, 1); + %posZ = (getWord(%obj.getSlotTransform(%x), 2) + %height[%x]); + //InitContainerRadiusSearch(%posXY @ " " @ %posZ, %radius[%x], %mask); + + while ((%objFound = ContainerSearchNext()) != 0) + { + if (%objFound != %obj) + { + if (%x == 1) + %turretFailed = true; + else + %stationFailed = true; + break; + } + } + } + + //If turret, station or both fail the send back the error message... + if (%turretFailed && %stationFailed) + return "Both Turret and Station are blocked and unable to deploy."; + if (%turretFailed) + return "Turret is blocked and unable to deploy."; + if (%stationFailed) + return "Station is blocked and unable to deploy."; + + //Check the station for collision with the Terrain + %mat = %obj.getTransform(); + for(%x = 1; %x < 7; %x+=2) + { + %startPos = MatrixMulPoint(%mat, %data.stationPoints[%x]); + %endPos = MatrixMulPoint(%mat, %data.stationPoints[%x+1]); + + //%rayCastObj = containerRayCast(%startPos, %endPos, $TypeMasks::TerrainObjectType, 0); + if (%rayCastObj) + return "Station is blocked by terrain and unable to deploy."; + } + + return ""; +} +function MobileBaseVehicle::checkTurretDistance(%data, %obj) +{ + %pos = getWords(%obj.getTransform(), 0, 2); + //InitContainerRadiusSearch(%pos, 100, $TypeMasks::TurretObjectType | $TypeMasks::InteriorObjectType); + while ((%objFound = ContainerSearchNext()) != 0) + { + if (%objFound.getType() & $TypeMasks::TurretObjectType) + { + if (%objFound.getDataBlock().ClassName $= "TurretBase") + return "Turret Base is in the area. Unable to deploy."; + } + else + { + %subStr = getSubStr(%objFound.interiorFile, 1, 4); + if (%subStr !$= "rock" && %subStr !$= "spir" && %subStr !$= "misc") + return "Building is in the area. Unable to deploy."; + } + } + return ""; +} + +function KillerMobileBaseVehicle::vehicleDeploy(%data, %obj, %player, %force) +{ + + if (VectorLen(%obj.getVelocity()) <= 0.1 || %force) + { + %deployMessage = ""; + if ( (%deployMessage = %data.checkTurretDistance(%obj)) $= "" || %force) + { + if (%obj.station $= "") + { + if ( (%deployMessage = %data.checkDeploy(%obj)) $= "" || %force) + { + %obj.station = new StaticShape() { + scale = "1 1 1"; + dataBlock = "MobileInvStation"; + lockCount = "0"; + homingCount = "0"; + team = %obj.team; + vehicle = %obj; + }; + %obj.station.startFade(0,0,true); + %obj.mountObject(%obj.station, 2); + %obj.station.getDataBlock().createTrigger(%obj.station); + %obj.station.setSelfPowered(); + %obj.station.playThread($PowerThread,"Power"); + %obj.station.playAudio($HumSound,StationHumSound); + %obj.station.vehicle = %obj; + + //[most] Only give mpb's nukes when enabled in options + if ($MPM::NukeMPB) + { + %obj.nuke=%obj.Mpm_Turret(); + %obj.nuke.ammo = %obj.nukeammo; + } + else //Otherwise give normal turret. + { + %obj.turret = new turret() + { + scale = "1 1 1"; + dataBlock = "MobileTurretBase"; + lockCount = "0"; + homingCount = "0"; + team = %obj.team; + }; + %obj.turret.setDamageLevel(%obj.getDamageLevel()); + %obj.mountObject(%obj.turret, 1); + %obj.turret.setSelfPowered(); + %obj.turret.playThread($PowerThread,"Power"); + %obj.turret.mountImage(MissileBarrelLarge, 0 ,false); + } + + + %obj.beacon = new BeaconObject() { + dataBlock = "DeployedBeacon"; + position = %obj.position; + rotation = %obj.rotation; + team = %obj.team; + }; + %obj.beacon.setBeaconType(friend); + %obj.beacon.setTarget(%obj.team); + // --------------------------------- + // z0dd - ZOD, 5/8/02. Invalid call. + //checkSpawnPos(%obj, 20); + } + } + else + { + %obj.station.setSelfPowered(); + %obj.station.playThread($PowerThread,"Power"); + //[most] //check if there "is" an turret + if (isObject(%obj.turret)) + { + %obj.turret.setSelfPowered(); + %obj.turret.playThread($PowerThread,"Power"); + } + //[most] + } + if (%deployMessage $= "" || %force) + { + //[most] + if (isObject(%obj.turret)) + { + if (%obj.turret.getTarget() == -1) + { + %obj.turret.setTarget(%obj.turret.target); + } + %obj.turret.setThreadDir($DeployThread, true); + %obj.turret.playThread($DeployThread,"deploy"); + %obj.turret.playAudio($DeploySound, MobileBaseTurretDeploySound); + } + if (isObject(%obj.nuke)) + %obj.nuke.mpm_all_on(); + //[most] + %obj.station.notDeployed = 1; + %obj.setThreadDir($DeployThread, true); + %obj.playThread($DeployThread,"deploy"); + %obj.playAudio($DeploySound, MobileBaseDeploySound); + %obj.deployed = 1; + %obj.deploySchedule = ""; + %obj.disableMove = true; + %obj.setFrozenState(true); + if (isObject(%obj.shield)) + %obj.shield.delete(); + + %obj.shield = new forceFieldBare() + { + scale = "1.22 1.8 1.1"; + dataBlock = "defaultTeamSlowFieldBare"; + team = %obj.team; + }; + %obj.shield.open(); + setTargetSensorData(%obj.getTarget(), MPBDeployedSensor); + } + } + if (%deployMessage !$= "") + messageClient(%player.client, '', %deployMessage); + + return true; + } + else + { + return false; + } +} + +function KillerMobileBaseVehicle::onEndSequence(%data, %obj, %thread) +{ + if (%thread == $DeployThread && !%obj.deployed) + { + %obj.unmountObject(%obj.station); + %obj.station.trigger.delete(); + %obj.station.delete(); + %obj.station = ""; + + %obj.beacon.delete(); + //[most] Handles removal of nuke. + if (isObject(%obj.nuke)) + { + %obj.nukeammo = %obj.nuke.ammo; + %obj.nuke.mpm_all_off(1); + %obj.unmountObject(%obj.nuke); + %obj.nuke.schedule(1500,"delete"); + } + if (isObject(%obj.turret)) + { + %obj.unmountObject(%obj.turret); + %obj.turret.delete(); + %obj.turret = ""; + } + //[most] + if (!%obj.immobilized) + { + %obj.disableMove = false; + %obj.setFrozenState(false); + } + setTargetSensorData(%obj.getTarget(), %data.sensorData); + } + else + { + %obj.station.startFade(0,0,false); + %obj.station.setThreadDir($DeployThread, true); + %obj.station.playThread($DeployThread,"deploy"); + %obj.station.playAudio($DeploySound, MobileBaseStationDeploySound); + %obj.station.goingOut = true; + %obj.shield.setTransform(%obj.getSlotTransform(3)); + %obj.shield.close(); + %obj.isDeployed = true; + %obj.noEnemyControl = 1; + } + + Parent::onEndSequence(%data, %obj, %thread); +} + + +function KillerMobileBaseVehicle::checkDeploy(%data, %obj) +{ + + %mask = $TypeMasks::VehicleObjectType | $TypeMasks::MoveableObjectType | + $TypeMasks::StaticShapeObjectType | $TypeMasks::ForceFieldObjectType | + $TypeMasks::ItemObjectType | $TypeMasks::PlayerObjectType | + $TypeMasks::TurretObjectType | //$TypeMasks::StaticTSObjectType | + $TypeMasks::InteriorObjectType; + + //%slot 1 = turret %slot 2 = station + %height[1] = 0; + %height[2] = 0; + %radius[1] = 2.4; + %radius[2] = 2.4; + %stationFailed = false; + %turretFailed = false; + + for(%x = 1; %x < 3; %x++) + { + %posXY = getWords(%obj.getSlotTransform(%x), 0, 1); + %posZ = (getWord(%obj.getSlotTransform(%x), 2) + %height[%x]); + //InitContainerRadiusSearch(%posXY @ " " @ %posZ, %radius[%x], %mask); + + while ((%objFound = ContainerSearchNext()) != 0) + { + if (%objFound != %obj) + { + if (%x == 1) + %turretFailed = true; + else + %stationFailed = true; + break; + } + } + } + + //If turret, station or both fail the send back the error message... + if (%turretFailed && %stationFailed) + return "Both Turret and Station are blocked and unable to deploy."; + if (%turretFailed) + return "Turret is blocked and unable to deploy."; + if (%stationFailed) + return "Station is blocked and unable to deploy."; + + //Check the station for collision with the Terrain + %mat = %obj.getTransform(); + for(%x = 1; %x < 7; %x+=2) + { + %startPos = MatrixMulPoint(%mat, %data.stationPoints[%x]); + %endPos = MatrixMulPoint(%mat, %data.stationPoints[%x+1]); + + //%rayCastObj = containerRayCast(%startPos, %endPos, $TypeMasks::TerrainObjectType, 0); + if (%rayCastObj) + return "Station is blocked by terrain and unable to deploy."; + } + + return ""; +} +function KillerMobileBaseVehicle::checkTurretDistance(%data, %obj) +{ + %pos = getWords(%obj.getTransform(), 0, 2); + //InitContainerRadiusSearch(%pos, 100, $TypeMasks::TurretObjectType | $TypeMasks::InteriorObjectType); + while ((%objFound = ContainerSearchNext()) != 0) + { + if (%objFound.getType() & $TypeMasks::TurretObjectType) + { + if (%objFound.getDataBlock().ClassName $= "TurretBase") + return "Turret Base is in the area. Unable to deploy."; + } + else + { + %subStr = getSubStr(%objFound.interiorFile, 1, 4); + if (%subStr !$= "rock" && %subStr !$= "spir" && %subStr !$= "misc") + return "Building is in the area. Unable to deploy."; + } + } + return ""; +} + + +//************************************************************** +//* VEHICLE INVENTORY MANAGEMENT +//************************************************************** + +//-------------------------------------------------------------- +// NUMBER OF PURCHASEABLE VEHICLES PER TEAM +//-------------------------------------------------------------- + +$VehicleRespawnTime = 15000; +$Vehiclemax[ScoutVehicle] = 4; +$Vehiclemax[SuperScoutVehicle] = 4; +$VehicleMax[AssaultVehicle] = 3; +$VehicleMax[MobileBaseVehicle] = 1; +$VehicleMax[ScoutFlyer] = 4; +$VehicleMax[BomberFlyer] = 2; +$VehicleMax[HAPCFlyer] = 2; +$VehicleMax[SuperHAPCFlyer] = 2; +$VehicleMax[Artillery] = 0; + + +function vehicleListRemove(%data, %obj) +{ + %blockName = %data.getName(); + for($i = 0; %i < $VehicleMax[%blockName]; %i++) + if ($VehicleInField[%obj.team, %blockName, %i] == %obj) + { + $VehicleInField[%obj.team, %blockName, %i] = 0; + $VehicleTotalCount[%obj.team, %blockName]--; + break; + } +} + +function vehicleListAdd(%blockName, %obj) +{ + for($i = 0; %i < $VehicleMax[%blockName]; %i++) + { + if ($VehicleInField[%obj.team, %blockName, %i] $= "" || $VehicleInField[%obj.team, %blockName, %i] == 0) + { + $VehicleInField[%obj.team, %blockName, %i] = %obj; + $VehicleTotalCount[%obj.team, %blockName]++; + break; + } + } +} + +function clearVehicleCount(%team) +{ + $VehicleTotalCount[%team, ScoutVehicle] = 0; + $VehicleTotalCount[%team, SuperScoutVehicle] = 0; + $VehicleTotalCount[%team, AssaultVehicle] = 0; + $VehicleTotalCount[%team, MobileBaseVehicle] = 0; + $VehicleTotalCount[%team, ScoutFlyer] = 0; + $VehicleTotalCount[%team, BomberFlyer] = 0; + $VehicleTotalCount[%team, HAPCFlyer] = 0; + $VehicleTotalCount[%team, SuperHAPCFlyer] = 0; + $VehicleTotalCount[%team, Artillery] = 0; +} + +//************************************************************** +//* VEHICLE HUD SEAT INDICATOR LIGHTS +//************************************************************** + +// --------------------------------------------------------- +// z0dd - ZOD, 6/18/02. Get the name of the vehicle node and +// pass to Armor::onMount and Armor::onDismount in player.cs +function findNodeName(%vehicle, %node) +{ + + %vName = %vehicle.getDataBlock().getName(); + if (%vName !$= "HAPCFlyer") + { + if (%node == 0) + return 'pilot'; + else if (%node == 1) + return 'gunner'; + else + return 'tailgunner'; + } + else + { + if (%node == 0) + return 'pilot'; + else if (%node == 1) + return 'tailgunner'; + else + return 'passenger'; + } +} +// End z0dd - ZOD +// --------------------------------------------------------- + +function findAIEmptySeat(%vehicle, %player) +{ + %dataBlock = %vehicle.getDataBlock(); + if (%dataBlock.getName() $= "BomberFlyer") + %num = 2; + else + %num = 1; + %node = -1; + for(%i = %num; %i < %dataBlock.numMountPoints; %i++) + { + if (!%vehicle.getMountNodeObject(%i)) + { + //cheap hack - for now, AI's will mount the next available node regardless of where they collided + %node = %i; + break; + } + } + + //return the empty seat + return %node; +} + +function findEmptySeat(%vehicle, %player, %forceNode) +{ + %minNode = 1; + %node = -1; + %dataBlock = %vehicle.getDataBlock(); + %dis = %dataBlock.minMountDist; + %playerPos = getWords(%player.getTransform(), 0, 2); + %message = ""; + if (%dataBlock.lightOnly) + { + if (%player.client.armor $= "Light" || %player.client.armor $= "Pure") + %minNode = 0; + else + %message = '\c2Only Scout Armors can pilot this vehicle.~wfx/misc/misc.error.wav'; + } + else if (%player.client.armor $= "Light" || %player.client.armor $= "Medium" || %player.client.armor $= "Pure") + %minNode = 0; + else + %minNode = findFirstHeavyNode(%dataBlock); + + if (%forceNode !$= "") + %node = %forceNode; + else + { + for(%i = 0; %i < %dataBlock.numMountPoints; %i++) + if (!%vehicle.getMountNodeObject(%i)) + { + %seatPos = getWords(%vehicle.getSlotTransform(%i), 0, 2); + %disTemp = VectorLen(VectorSub(%seatPos, %playerPos)); + if (%disTemp <= %dis) + { + %node = %i; + %dis = %disTemp; + } + } + } + if (%node != -1 && %node < %minNode) + { + if (%message $= "") + { + if (%node == 0) + %message = '\c2Only Scout, Assault or Pure Armors can pilot this vehicle.~wfx/misc/misc.error.wav'; + else + %message = '\c2Only Scout, Assault or Pure Armors can use that position.~wfx/misc/misc.error.wav'; + } + + if (!%player.noSitMessage) + { + %player.noSitMessage = true; + %player.schedule(2000, "resetSitMessage"); + messageClient(%player.client, 'MsgArmorCantMountVehicle', %message); + } + %node = -1; + } + return %node; +} + +function findFirstHeavyNode(%data) +{ + for(%i = 0; %i < %data.numMountPoints; %i++) + if (%data.mountPose[%i] $= "") + return %i; + return %data.numMountPoints; +} + +//************************************************************** +//* DAMAGE FUNCTIONS +//************************************************************** + +function VehicleData::damageObject(%data, %targetObject, %sourceObject, %position, %amount, %damageType, %momVec, %theClient, %proj) +{ + + if (%proj !$= "") + { + if (%amount > 0 && %targetObject.lastDamageProj !$= %proj) + { + %targetObject.lastDamageProj = %proj; + %targetObject.lastDamageAmount = %amount; + } + else if (%targetObject.lastDamageAmount < %amount) + %amount = %amount - %targetObject.lastDamageAmount; + else + return; + } + +// TODO - check + // check for team damage + if (isObject(%sourceObject)) + %sourceClient = %sourceObject ? %sourceObject.getOwnerClient() : 0; + %targetTeam = getTargetSensorGroup(%targetObject.getTarget()); + + if (%sourceClient) + %sourceTeam = %sourceClient.getSensorGroup(); + else if (isObject(%sourceObject) && %sourceObject.getClassName() $= "Turret") + %sourceTeam = getTargetSensorGroup(%sourceObject.getTarget()); + else + %sourceTeam = %sourceObject ? getTargetSensorGroup(%sourceObject.getTarget()) : -1; + + // vehicles no longer obey team damage -JR +// if (!$teamDamage && (%targetTeam == %sourceTeam) && %targetObject.getDamagePercent() > 0.5) +// return; + //but we do want to track the destroyer + if (%sourceObject) + { + %targetObject.lastDamagedBy = %sourceObject; + %targetObject.lastDamageType = %damageType; + } + else + %targetObject.lastDamagedBy = 0; + + + // Scale damage type & include shield calculations... + if (%data.isShielded) + %amount = %data.checkShields(%targetObject, %position, %amount, %damageType); + + + %damageScale = %data.damageScale[%damageType]; + if (%damageScale !$= "") + %amount *= %damageScale; + + if (%amount != 0) + %targetObject.applyDamage(%amount); + + if (%targetObject.getDamageState() $= "Destroyed" ) + { + if ( %momVec !$= "") + %targetObject.setMomentumVector(%momVec); + } +} + +function VehicleData::onImpact(%data, %vehicleObject, %collidedObject, %vec, %vecLen) +{ + + if (%vecLen > %data.minImpactSpeed) + %data.damageObject(%vehicleObject, 0, VectorAdd(%vec, %vehicleObject.getPosition()), + %vecLen * %data.speedDamageScale, $DamageType::Ground); + + // associated "crash" sounds + if (%vecLen > %vDataBlock.hardImpactSpeed) + %vehicleObject.playAudio(0, %vDataBlock.hardImpactSound); + else if (%vecLen > %vDataBlock.softImpactSpeed) + %vehicleObject.playAudio(0, %vDataBlock.softImpactSound); +} + +//************************************************************** +//* VEHICLE TIMEOUTS +//************************************************************** + +function vehicleAbandonTimeOut(%vehicle) +{ + if (%vehicle.getDatablock().cantAbandon $= "" && %vehicle.lastPilot $= "") + { + for(%i = 0; %i < %vehicle.getDatablock().numMountPoints; %i++) + if (%vehicle.getMountNodeObject(%i)) + { + %passenger = %vehicle.getMountNodeObject(%i); + if (%passenger.lastVehicle !$= "") + schedule(2400, %passenger.lastVehicle,"vehicleAbandonTimeOut", %passenger.lastVehicle); + %passenger.lastVehicle = %vehicle; + %vehicle.lastPilot = %passenger; + return; + } + + if (%vehicle.respawnTime !$= "") + %vehicle.marker.schedule = %vehicle.marker.data.schedule(%vehicle.respawnTime, "respawn", %vehicle.marker); + %vehicle.mountable = 0; + %vehicle.startFade(2400, 0, true); + %vehicle.schedule(2401, "delete"); + } +} + +//------------------------------------------------------------------------------ +function HoverVehicleData::create(%block, %team, %oldObj) +{ + if (%oldObj $= "") + { + %obj = new HoverVehicle() + { + dataBlock = %block; + respawn = "0"; + teamBought = %team; + team = %team; + }; + } + else + { + %obj = new HoverVehicle() + { + dataBlock = %data; + respawn = "0"; + teamBought = %team; + team = %team; + mountable = %oldObj.mountable; + disableMove = %oldObj.disableMove; + resetPos = %oldObj.resetPos; + respawnTime = %oldObj.respawnTime; + marker = %oldObj; + }; + } + return(%obj); +} + +function WheeledVehicleData::create(%data, %team, %oldObj) +{ + if (%oldObj $= "") + { + %obj = new WheeledVehicle() + { + dataBlock = %data; + respawn = "0"; + teamBought = %team; + team = %team; + }; + } + else + { + %obj = new WheeledVehicle() + { + dataBlock = %data; + respawn = "0"; + teamBought = %team; + team = %team; + mountable = %oldObj.mountable; + disableMove = %oldObj.disableMove; + resetPos = %oldObj.resetPos; + deployed = %oldObj.deployed; + respawnTime = %oldObj.respawnTime; + marker = %oldObj; + }; + } + + return(%obj); +} + +function FlyingVehicleData::create(%data, %team, %oldObj) +{ + if (%oldObj $= "") + { + %obj = new FlyingVehicle() + { + dataBlock = %data; + respawn = "0"; + teamBought = %team; + team = %team; + }; + } + else + { + %obj = new FlyingVehicle() + { + dataBlock = %data; + teamBought = %team; + team = %team; + mountable = %oldObj.mountable; + disableMove = %oldObj.disableMove; + resetPos = %oldObj.resetPos; + respawnTime = %oldObj.respawnTime; + marker = %oldObj; + }; + } + + return(%obj); +} + +function FlyingVehicleData::switchSidesSetPos(%data, %oldObj) +{ + %team = %oldObj.curTeam == 1 ? 2 : 1; + %oldObj.curTeam = %team; + %obj = new FlyingVehicle() + { + dataBlock = %data; + teamBought = %team; + team = %team; + mountable = %oldObj.mountable; + disableMove = %oldObj.disableMove; + resetPos = %oldObj.resetPos; + respawnTime = %oldObj.respawnTime; + marker = %oldObj; + }; + %obj.setTransform(%oldObj.getTransform()); + + return(%obj); +} + +function WheeledVehicleData::switchSidesSetPos(%data, %oldObj) +{ + %team = %oldObj.curTeam == 1 ? 2 : 1; + %oldObj.curTeam = %team; + %obj = new WheeledVehicle() + { + dataBlock = %data; + respawn = "0"; + teamBought = %team; + team = %team; + mountable = %oldObj.mountable; + disableMove = %oldObj.disableMove; + resetPos = %oldObj.resetPos; + deployed = %oldObj.deployed; + respawnTime = %oldObj.respawnTime; + marker = %oldObj; + }; + %obj.setTransform(%oldObj.getTransform()); + return(%obj); +} + +function HoverVehicleData::switchSides(%data, %oldObj) +{ + %team = %oldObj.curTeam == 1 ? 2 : 1; + %oldObj.curTeam = %team; + %obj = new HoverVehicle() + { + dataBlock = %data; + respawn = "0"; + teamBought = %team; + team = %team; + mountable = %oldObj.mountable; + disableMove = %oldObj.disableMove; + resetPos = %oldObj.resetPos; + respawnTime = %oldObj.respawnTime; + marker = %oldObj; + }; + %obj.setTransform(%oldObj.getTransform()); + return(%obj); +} + +function resetNonStaticObjPositions() +{ + MissionGroup.setupPositionMarkers(false); + MissionCleanup.positionReset(); +} + +function next(%team) +{ + ResetObjsPositions(%team); +} + +function SimGroup::positionReset(%group) +{ + for(%i = %group.getCount() - 1; %i >=0 ; %i--) + { + %obj = %group.getObject(%i); + if (%obj.resetPos && %obj.getName() !$= PosMarker) + %obj.delete(); + else + %obj.positionReset(); + } + + for(%i = 0; %i < %group.getCount(); %i++) + { + %obj = %group.getObject(%i); + if (%obj.getName() $= PosMarker) + { + cancel(%obj.schedule); + %newObj = %obj.data.switchSidesSetPos(%obj); + MissionCleanup.add(%newObj); + setTargetSensorGroup(%newObj.target, %newObj.team); + } + else + %obj.positionReset(); + } +} + +function VehicleData::respawn(%data, %marker) +{ + %mask = $TypeMasks::PlayerObjectType | $TypeMasks::VehicleObjectType | $TypeMasks::TurretObjectType; + InitContainerRadiusSearch(%marker.getWorldBoxCenter(), %data.checkRadius, %mask); + if (containerSearchNext() == 0) + { + %newObj = %data.create(%marker.curTeam, %marker); + %newObj.startFade(1000, 0, false); + %newObj.setTransform(%marker.getTransform()); + + setTargetSensorGroup(%newObj.target, %newObj.team); + MissionCleanup.add(%newObj); + } + else + { + %marker.schedule = %data.schedule(3000, "respawn", %marker); + } +} + +function SimObject::positionReset(%group, %team) +{ + //Used to avoid warnings +} + +function Terraformer::positionReset(%group, %team) +{ + //Used to avoid warnings +} + +function SimGroup::setupPositionMarkers(%group, %create) +{ + for(%i = %group.getCount() - 1; %i >= 0; %i--) + { + %obj = %group.getObject(%i); + if (%obj.resetPos || %obj.respawnTime !$= "") + { + if (%create) + { + %marker = %obj.getDataBlock().createPositionMarker(%obj); + MissionCleanup.add(%marker); + %obj.marker = %marker; + } + else + { + %obj.delete(); + } + } + else + %obj.setupPositionMarkers(%create); + } +} + +function SimObject::setupPositionMarkers(%group, %create) +{ + //Used to avoid warnings +} + +function VehicleData::createPositionMarker(%data, %obj) +{ + %marker = new Trigger(PosMarker) + { + dataBlock = markerTrigger; + mountable = %obj.mountable; + disableMove = %obj.disableMove; + resetPos = %obj.resetPos; + data = %obj.getDataBlock().getName(); + deployed = %obj.deployed; + curTeam = %obj.team; + respawnTime = %obj.respawnTime; + }; + %marker.setTransform(%obj.getTransform()); + return %marker; +} + +function VehicleData::hasDismountOverrides(%data, %obj) +{ + return false; +} + diff --git a/scripts/vehicles/vehicle_artillery.cs b/scripts/vehicles/vehicle_artillery.cs new file mode 100644 index 0000000..20f5478 --- /dev/null +++ b/scripts/vehicles/vehicle_artillery.cs @@ -0,0 +1,780 @@ +//************************************************************** +// Long Range Artillery +//************************************************************** +//************************************************************** +// SOUNDS +//************************************************************** + +datablock AudioProfile(ArtillerySkid) +{ + filename = "fx/vehicles/tank_skid.wav"; + description = ClosestLooping3d; + preload = true; +}; + +datablock AudioProfile(ArtilleryEngineSound) +{ + filename = "fx/vehicles/tank_engine.wav"; + description = AudioDefaultLooping3d; + preload = true; +}; + +datablock AudioProfile(ArtilleryThrustSound) +{ + filename = "fx/vehicles/tank_boost.wav"; + description = AudioDefaultLooping3d; + preload = true; +}; + +datablock AudioProfile(ArtilleryChaingunFireSound) +{ + filename = "fx/vehicles/tank_chaingun.wav"; + description = AudioDefaultLooping3d; + preload = true; +}; + +datablock AudioProfile(ArtilleryChaingunReloadSound) +{ + filename = "fx/weapons/chaingun_dryfire.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(TankChaingunProjectile) +{ + filename = "fx/weapons/chaingun_projectile.wav"; + description = ProjectileLooping3d; + preload = true; +}; + +datablock AudioProfile(ArtilleryTurretActivateSound) +{ + filename = "fx/vehicles/tank_activate.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(ArtilleryChaingunDryFireSound) +{ + filename = "fx/weapons/chaingun_dryfire.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(ArtilleryChaingunIdleSound) +{ + filename = "fx/misc/diagnostic_on.wav"; + description = ClosestLooping3d; + preload = true; +}; + +datablock AudioProfile(ArtilleryMortarDryFireSound) +{ + filename = "fx/weapons/mortar_dryfire.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(ArtilleryMortarFireSound) +{ + filename = "fx/vehicles/tank_mortar_fire.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(ArtilleryMortarReloadSound) +{ + filename = "fx/weapons/mortar_reload.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(ArtilleryMortarIdleSound) +{ + filename = "fx/misc/diagnostic_on.wav"; + description = ClosestLooping3d; + preload = true; +}; + +//************************************************************** +// LIGHTS +//************************************************************** +datablock RunningLightData(TankLight1) +{ + radius = 1.5; + color = "1.0 1.0 1.0 0.2"; + nodeName = "Headlight_node01"; + direction = "0.0 1.0 0.0"; + texture = "special/headlight4"; +}; + +datablock RunningLightData(TankLight2) +{ + radius = 1.5; + color = "1.0 1.0 1.0 0.2"; + nodeName = "Headlight_node02"; + direction = "0.0 1.0 0.0"; + texture = "special/headlight4"; +}; + +datablock RunningLightData(TankLight3) +{ + radius = 1.5; + color = "1.0 1.0 1.0 0.2"; + nodeName = "Headlight_node03"; + direction = "0.0 1.0 0.0"; + texture = "special/headlight4"; +}; + +datablock RunningLightData(TankLight4) +{ + radius = 1.5; + color = "1.0 1.0 1.0 0.2"; + nodeName = "Headlight_node04"; + direction = "0.0 1.0 0.0"; + texture = "special/headlight4"; +}; + +//************************************************************** +// VEHICLE CHARACTERISTICS +//************************************************************** + +datablock HoverVehicleData(Artillery) : TankDamageProfile +{ + spawnOffset = "0 0 4"; + + floatingGravMag = 4.5; + + catagory = "Vehicles"; + shapeFile = "vehicle_grav_tank.dts"; + multipassenger = true; + computeCRC = true; + renderWhenDestroyed = false; + + weaponNode = 1; + + debrisShapeName = "vehicle_land_assault_debris.dts"; + debris = ShapeDebris; + + drag = 0.0; + density = 0.9; + + mountPose[0] = sitting; + mountPose[1] = sitting; + numMountPoints = 2; + isProtectedMountPoint[0] = true; + isProtectedMountPoint[1] = true; + + cameraMaxDist = 20; + cameraOffset = 3; + cameraLag = 1.5; + explosion = LargeGroundVehicleExplosion2; + explosionDamage = 0.5; + explosionRadius = 5.0; + + maxSteeringAngle = 0.5; // 20 deg. + + maxDamage = 1.575; + destroyedLevel = 1.575; + + isShielded = true; + rechargeRate = 1.0; + energyPerDamagePoint = 300; + maxEnergy = 400; + minJetEnergy = 15; + jetEnergyDrain = 2.0; + + // Rigid Body + mass = 4000; + bodyFriction = 0.8; + bodyRestitution = 0.5; + minRollSpeed = 3; + gyroForce = 400; + gyroDamping = 0.3; + stabilizerForce = 20; + minDrag = 10; + softImpactSpeed = 15; // Play SoftImpact Sound + hardImpactSpeed = 18; // Play HardImpact Sound + + // Ground Impact Damage (uses DamageType::Ground) + minImpactSpeed = 17; + speedDamageScale = 0.060; + + // Object Impact Damage (uses DamageType::Impact) + collDamageThresholdVel = 18; + collDamageMultiplier = 0.045; + + dragForce = 40 / 20; + vertFactor = 0.0; + floatingThrustFactor = 0.15; + + mainThrustForce = 50; + reverseThrustForce = 40; + strafeThrustForce = 40; + turboFactor = 1.7; + + brakingForce = 25; + brakingActivationSpeed = 4; + + stabLenMin = 3.25; + stabLenMax = 4; + stabSpringConstant = 50; + stabDampingConstant = 20; + + gyroDrag = 20; + normalForce = 20; + restorativeForce = 10; + steeringForce = 15; + rollForce = 5; + pitchForce = 3; + + dustEmitter = TankDustEmitter; + triggerDustHeight = 3.5; + dustHeight = 1.0; + dustTrailEmitter = TireEmitter; + dustTrailOffset = "0.0 -1.0 0.5"; + triggerTrailHeight = 3.6; + dustTrailFreqMod = 15.0; + + jetSound = ArtilleryThrustSound; + engineSound = ArtilleryEngineSound; + floatSound = ArtillerySkid; + softImpactSound = GravSoftImpactSound; + hardImpactSound = HardImpactSound; + wheelImpactSound = WheelImpactSound; + + forwardJetEmitter = TankJetEmitter; + + // + softSplashSoundVelocity = 5.0; + mediumSplashSoundVelocity = 10.0; + hardSplashSoundVelocity = 15.0; + exitSplashSoundVelocity = 10.0; + + exitingWater = VehicleExitWaterMediumSound; + impactWaterEasy = VehicleImpactWaterSoftSound; + impactWaterMedium = VehicleImpactWaterMediumSound; + impactWaterHard = VehicleImpactWaterMediumSound; + waterWakeSound = VehicleWakeMediumSplashSound; + + minMountDist = 4; + + damageEmitter[0] = SmallLightDamageSmoke; + damageEmitter[1] = SmallHeavyDamageSmoke; + damageEmitter[2] = DamageBubbles; + damageEmitterOffset[0] = "0.0 -1.5 3.5 "; + damageLevelTolerance[0] = 0.3; + damageLevelTolerance[1] = 0.7; + numDmgEmitterAreas = 1; + + splashEmitter[0] = VehicleFoamDropletsEmitter; + splashEmitter[1] = VehicleFoamEmitter; + + shieldImpact = VehicleShieldImpact; + + cmdCategory = "Tactical"; + cmdIcon = CMDGroundTankIcon; + cmdMiniIconName = "commander/MiniIcons/com_tank_grey"; + targetNameTag = 'Beowulf'; + targetTypeTag = 'Long Range Artillery'; + sensorData = VehiclePulseSensor; + + checkRadius = 5.5535; + observeParameters = "1 10 10"; + runningLight[0] = TankLight1; + runningLight[1] = TankLight2; + runningLight[2] = TankLight3; + runningLight[3] = TankLight4; + shieldEffectScale = "0.9 1.0 0.6"; + showPilotInfo = 1; +}; + +//************************************************************** +// WEAPONS +//************************************************************** + +//------------------------------------- +// Artillery CHAINGUN (projectile) +//------------------------------------- + +datablock TracerProjectileData(ArtilleryChaingunBullet) +{ + doDynamicClientHits = true; + + projectileShapeName = ""; + directDamage = 0.16; + directDamageType = $DamageType::TankChaingun; + hasDamageRadius = false; + splash = ChaingunSplash; + + kickbackstrength = 0.0; + sound = TankChaingunProjectile; + + dryVelocity = 425.0; + wetVelocity = 100.0; + velInheritFactor = 1.0; + fizzleTimeMS = 3000; + lifetimeMS = 3000; + explodeOnDeath = false; + reflectOnWaterImpactAngle = 0.0; + explodeOnWaterImpact = false; + deflectionOnWaterImpact = 0.0; + fizzleUnderwaterMS = 3000; + + tracerLength = 15.0; + tracerAlpha = false; + tracerMinPixels = 6; + tracerColor = 211.0/255.0 @ " " @ 215.0/255.0 @ " " @ 120.0/255.0 @ " 0.75"; + tracerTex[0] = "special/tracer00"; + tracerTex[1] = "special/tracercross"; + tracerWidth = 0.10; + crossSize = 0.20; + crossViewAng = 0.990; + renderCross = true; + + decalData[0] = ChaingunDecal1; + decalData[1] = ChaingunDecal2; + decalData[2] = ChaingunDecal3; + decalData[3] = ChaingunDecal4; + decalData[4] = ChaingunDecal5; + decalData[5] = ChaingunDecal6; + + activateDelayMS = 100; + + explosion = ChaingunExplosion; +}; + +//------------------------------------- +// Artillery CHAINGUN CHARACTERISTICS +//------------------------------------- + +datablock TurretData(ArtilleryPlasmaTurret) : TurretDamageProfile +{ + className = VehicleTurret; + catagory = "Turrets"; + shapeFile = "Turret_tank_base.dts"; + preload = true; + + mass = 1.0; // Not really relevant + + maxEnergy = 1; + maxDamage = Artillery.maxDamage; + destroyedLevel = Artillery.destroyedLevel; + repairRate = 0; + + // capacitor + maxCapacitorEnergy = 250; + capacitorRechargeRate = 1.0; + + thetaMin = 0; + thetaMax = 100; + + inheritEnergyFromMount = true; + firstPersonOnly = true; + useEyePoint = true; + numWeapons = 1; + + cameraDefaultFov = 90.0; + cameraMinFov = 5.0; + cameraMaxFov = 120.0; + + targetNameTag = 'Artillery Chaingun'; + targetTypeTag = 'Turret'; +}; + +datablock TurretImageData(ArtilleryTurretParam) +{ + mountPoint = 2; + shapeFile = "turret_muzzlepoint.dts"; + + projectile = ArtilleryChaingunBullet; + projectileType = TracerProjectile; + + useCapacitor = true; + usesEnergy = true; + + // Turret parameters + activationMS = 10; + deactivateDelayMS = 15; + thinkTimeMS = 20; + degPerSecTheta = 500; + degPerSecPhi = 500; + + attackRadius = 750; +}; + +datablock TurretImageData(ArtilleryPlasmaTurretBarrel) +{ + shapeFile = "turret_tank_barrelchain.dts"; + mountPoint = 1; + + projectile = ArtilleryChaingunBullet; + projectileType = TracerProjectile; + + casing = ShellDebris; + shellExitDir = "1.0 0.3 1.0"; + shellExitOffset = "0.15 -0.56 -0.1"; + shellExitVariance = 15.0; + shellVelocity = 3.0; + + projectileSpread = 12.0 / 1000.0; + + useCapacitor = true; + usesEnergy = true; + useMountEnergy = true; + fireEnergy = 3.75; + minEnergy = 15.0; + + // Turret parameters + activationMS = 400; + deactivateDelayMS = 50; + thinkTimeMS = 20; + degPerSecTheta = 360; + degPerSecPhi = 360; + attackRadius = 750; + + // State transitions + stateName[0] = "Activate"; + stateTransitionOnNotLoaded[0] = "Dead"; + stateTransitionOnLoaded[0] = "ActivateReady"; + stateSound[0] = ArtilleryTurretActivateSound; + + stateName[1] = "ActivateReady"; + stateSequence[1] = "Activate"; + stateSound[1] = ArtilleryTurretActivateSound; + stateTimeoutValue[1] = 0.1; + stateTransitionOnTimeout[1] = "Ready"; + stateTransitionOnNotLoaded[1] = "Deactivate"; + + stateName[2] = "Ready"; + stateTransitionOnNotLoaded[2] = "Deactivate"; + stateTransitionOnTriggerDown[2] = "Fire"; + stateTransitionOnNoAmmo[2] = "NoAmmo"; + + stateName[3] = "Fire"; + stateSequence[3] = "Fire"; + stateSequenceRandomFlash[3] = true; + stateFire[3] = true; + stateAllowImageChange[3] = false; + stateSound[3] = ArtilleryChaingunFireSound; + stateScript[3] = "onFire"; + stateTimeoutValue[3] = 0.1; + stateTransitionOnTimeout[3] = "Fire"; + stateTransitionOnTriggerUp[3] = "Reload"; + stateTransitionOnNoAmmo[3] = "noAmmo"; + + stateName[4] = "Reload"; + stateSequence[4] = "Reload"; + stateTimeoutValue[4] = 0.1; + stateAllowImageChange[4] = false; + stateTransitionOnTimeout[4] = "Ready"; + stateTransitionOnNoAmmo[4] = "NoAmmo"; + stateWaitForTimeout[4] = true; + + stateName[5] = "Deactivate"; + stateSequence[5] = "Activate"; + stateDirection[5] = false; + stateTimeoutValue[5] = 0.1; + stateTransitionOnTimeout[5] = "ActivateReady"; + + stateName[6] = "Dead"; + stateTransitionOnLoaded[6] = "ActivateReady"; + stateTransitionOnTriggerDown[6] = "DryFire"; + + stateName[7] = "DryFire"; + stateSound[7] = ArtilleryChaingunDryFireSound; + stateTimeoutValue[7] = 0.1; + stateTransitionOnTimeout[7] = "NoAmmo"; + + stateName[8] = "NoAmmo"; + stateTransitionOnAmmo[8] = "Reload"; + stateSequence[8] = "NoAmmo"; + stateTransitionOnTriggerDown[8] = "DryFire"; +}; + +datablock TurretImageData(ArtilleryPlasmaTurretBarrel2) : ArtilleryPlasmaTurretBarrel +{ + mountPoint = 0; +}; + +datablock ShapeBaseImageData(ArtilleryCannonTurret) +{ + className = WeaponImage; + shapeFile = "turret_tank_barrelmortar.dts"; + mountPoint = 3; + offset = "2 -2.5 1.5"; + rotation = "-1 0 0 80"; + activationMS = 100; + deactivateDelayMS = 150; + thinkTimeMS = 20; + degPerSecTheta = 500; + degPerSecPhi = 500; + attackRadius = 500; +}; + +datablock ShapeBaseImageData(ArtilleryCannonTurret2) +{ + className = WeaponImage; + shapeFile = "turret_tank_barrelmortar.dts"; + mountPoint = 3; + offset = "-2 -2.5 1.5"; + rotation = "-1 0 0 80"; + activationMS = 100; + deactivateDelayMS = 150; + thinkTimeMS = 20; + degPerSecTheta = 500; + degPerSecPhi = 500; + attackRadius = 500; +}; + +function Artillery::onAdd(%this, %obj) +{ + Parent::onAdd(%this, %obj); + %turret = TurretData::create(ArtilleryPlasmaTurret); + %turret.selectedWeapon = 1; + MissionCleanup.add(%turret); + %turret.team = %obj.teamBought; + %turret.setSelfPowered(); + %obj.mountObject(%turret, 10); + %turret.setCapacitorRechargeRate( %turret.getDataBlock().capacitorRechargeRate ); + %obj.turretObject = %turret; + %turret.setAutoFire(false); + %turret.mountImage(ArtilleryPlasmaTurretBarrel, 2); + %turret.mountImage(ArtilleryPlasmaTurretBarrel2, 4); + %turret.mountImage(AssaultTurretParam, 0); + %obj.schedule(6000, "playThread", $ActivateThread, "activate"); + setTargetSensorGroup(%turret.getTarget(), %turret.team); + setTargetNeverVisMask(%turret.getTarget(), 0xffffffff); + + %obj.mountImage(ArtilleryCannonTurret, 3); + %obj.mountImage(ArtilleryCannonTurret2, 4); + schedule(6100, 0, "ArtilleryLookForTarget", %obj); +} + +function Artillery::deleteAllMounted(%data, %obj) +{ + %turret = %obj.getMountNodeObject(10); + if (%turret) + { + if(%client = %turret.getControllingClient()) + { + %client.player.setControlObject(%client.player); + %client.player.mountImage(%client.player.lastWeapon, $WeaponSlot); + %client.player.mountVehicle = false; + } + %turret.delete(); + } + %turret = %obj.getMountNodeObject(10); + if(%turret) + %turret.delete(); +} + +function Artillery::playerMounted(%data, %obj, %player, %node) +{ + if(%node == 0) + commandToClient(%player.client, 'setHudMode', 'Pilot', "Assault", %node); + else if(%node == 1) + { + %turret = %obj.getMountNodeObject(10); + %player.vehicleTurret = %turret; + %player.setTransform("0 0 0 0 0 1 0"); + %player.lastWeapon = %player.getMountedImage($WeaponSlot); + %player.unmountImage($WeaponSlot); + if(!%player.client.isAIControlled()) + { + %player.setControlObject(%turret); + %player.client.setObjectActiveImage(%turret, 2); + } + %turret.turreteer = %player; + $aWeaponActive = 0; + commandToClient(%player.client,'SetWeaponryVehicleKeys', true); + %obj.getMountNodeObject(10).selectedWeapon = 1; + commandToClient(%player.client, 'setHudMode', 'Pilot', "Assault", %node); + } + if( %player.client.observeCount > 0 ) + resetObserveFollow( %player.client, false ); + %passString = buildPassengerString(%obj); + for(%i = 0; %i < %data.numMountPoints; %i++) + if(%obj.getMountNodeObject(%i) > 0) + commandToClient(%obj.getMountNodeObject(%i).client, 'checkPassengers', %passString); +} + +function ArtilleryPlasmaTurret::onDamage(%data, %obj) +{ + %newDamageVal = %obj.getDamageLevel(); + if(%obj.lastDamageVal !$= "") + if(isObject(%obj.getObjectMount()) && %obj.lastDamageVal > %newDamageVal) + %obj.getObjectMount().setDamageLevel(%newDamageVal); + %obj.lastDamageVal = %newDamageVal; +} + +function ArtilleryPlasmaTurret::damageObject(%this, %targetObject, %sourceObject, %position, %amount, %damageType ,%vec, %client, %projectile) +{ + %vehicle = %targetObject.getObjectMount(); + if(%vehicle) + %vehicle.getDataBlock().damageObject(%vehicle, %sourceObject, %position, %amount, %damageType, %vec, %client, %projectile); +} + +function ArtilleryPlasmaTurret::onTrigger(%data, %obj, %trigger, %state) +{ + switch (%trigger) + { + case 0: + %obj.fireTrigger = %state; + if(%state) + { + %obj.setImageTrigger(2, true); + %obj.setImageTrigger(4, true); + } + else + { + %obj.setImageTrigger(2, false); + %obj.setImageTrigger(4, false); + } + case 2: + if(%state) + %obj.getDataBlock().playerDismount(%obj); + } +} + +function ArtilleryPlasmaTurret::playerDismount(%data, %obj) +{ + %obj.fireTrigger = 0; + %obj.setImageTrigger(2, false); + %obj.setImageTrigger(4, false); + %client = %obj.getControllingClient(); + %client.player.mountImage(%client.player.lastWeapon, $WeaponSlot); + %client.player.mountVehicle = false; + setTargetSensorGroup(%obj.getTarget(), 0); + setTargetNeverVisMask(%obj.getTarget(), 0xffffffff); +} + +function ArtilleryCannonTurret::onMount(%this, %obj, %slot) +{ +} + +function ArtilleryCannonTurret::onUnmount(%this, %obj, %slot) +{ +} + +function ArtilleryCannonTurret2::onMount(%this, %obj, %slot) +{ +} + +function ArtilleryCannonTurret2::onUnmount(%this, %obj, %slot) +{ +} + +function ArtilleryLookForTarget(%obj) +{ + if (isObject(%obj)) + { + if (%obj.lastcannon == 3) + %obj.lastcannon = 4; + else + %obj.lastcannon = 3; + %pos = %obj.getMuzzlePoint(%obj.lastcannon); + %vec = %obj.getMuzzleVector(%obj.lastcannon); + %count = ClientGroup.getCount(); + %mainDist = 1760; + %targetPos = ""; + %damageMasks = $TypeMasks::PlayerObjectType | $TypeMasks::VehicleObjectType | + $TypeMasks::StationObjectType | $TypeMasks::GeneratorObjectType | + $TypeMasks::SensorObjectType | $TypeMasks::TurretObjectType | + $TypeMasks::InteriorObjectType | $TypeMasks::TerrainObjectType; + for (%i=0;%i<%count;%i++) + { + %obj2 = ClientGroup.getObject(%i); + %player = %obj2.player; + if (%player) + { + if ((%player.team == %obj.team) && (%player.posLaze)) + { + %muzzlePos = %player.getMuzzlePoint($WeaponSlot); + %muzzleVec = %player.getMuzzleVector($WeaponSlot); + %endPos = VectorAdd(%muzzlePos, VectorScale(%muzzleVec, 1000)); + %hit = ContainerRayCast(%muzzlePos, %endPos, %damageMasks, %player); + if (%hit) + %pos2 = getWords(%hit, 1, 3); + %dist = VectorDist(%pos, %pos2); + if ((%dist > 2) && (%dist < 7500) && (%dist < %mainDist)) + { + %targetPos = %pos2; + %mainDist = %dist; + } + } + } + } + if (%targetPos) + { + %p = new GrenadeProjectile() { + dataBlock = ArtilleryShot; + initialDirection = %vec; + initialPosition = %pos; + sourceObject = %obj.lastpilot; + sourceSlot = %obj.lastcannon; + vehicleObject = %obj; + }; + MissionCleanup.add(%p); + schedule(200, 0, ArtilleryShotDrop, %p, %pos, %targetPos); + } + schedule (50, 0, ArtilleryLookForTarget, %obj); + } +} + +function ArtilleryShotDrop(%b, %pos, %pos2) +{ + if (isObject(%b)) + { + %dist = VectorDist(%pos, %pos2); + %accuracy = %dist / 100; + %b.schedule(50, "delete"); + %pos3 = VectorAdd(%pos2, "0 0 500"); + %vec = "0 0 -1"; + %x = (getRandom() - 0.5) * 2 * 3.1415926 * %accuracy / 10000; + %y = (getRandom() - 0.5) * 2 * 3.1415926 * %accuracy / 10000; + %z = (getRandom() - 0.5) * 2 * 3.1415926 * %accuracy / 10000; + %mat = MatrixCreateFromEuler(%x @ " " @ %y @ " " @ %z); + %vec = MatrixMulVector(%mat, %vec); + %p = new GrenadeProjectile() { + dataBlock = ArtilleryShot; + initialDirection = %vec; + initialPosition = %pos3; + sourceObject = %b.sourceObject; + sourceSlot = %b.sourceSlot; + vehicleObject = %b.vehicleObject; + }; + MissionCleanup.add(%p); + } +} + +datablock GrenadeProjectileData(ArtilleryShot) +{ + projectileShapeName = "mortar_projectile.dts"; + emitterDelay = -1; + directDamage = 0.0; + hasDamageRadius = true; + indirectDamage = 1.0; + damageRadius = 25.0; + radiusDamageType = $DamageType::Mortar; + kickBackStrength = 2500; + scale = "2 2 2"; + 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 = 10; + muzzleVelocity = 300; + drag = 0.01; + sound = MortarProjectileSound; + hasLight = true; + lightRadius = 4; + lightColor = "0.05 0.2 0.05"; + hasLightUnderwaterColor = true; + underWaterLightColor = "0.05 0.075 0.2"; +}; diff --git a/scripts/vehicles/vehicle_bomber.cs b/scripts/vehicles/vehicle_bomber.cs new file mode 100644 index 0000000..a9e9275 --- /dev/null +++ b/scripts/vehicles/vehicle_bomber.cs @@ -0,0 +1,997 @@ +//************************************************************** +// THUNDERSWORD BOMBER +//************************************************************** +//************************************************************** +// SOUNDS +//************************************************************** +datablock EffectProfile(BomberFlyerEngineEffect) +{ + effectname = "vehicles/bomber_engine"; + minDistance = 5.0; + maxDistance = 10.0; +}; + +datablock EffectProfile(BomberFlyerThrustEffect) +{ + effectname = "vehicles/bomber_boost"; + minDistance = 5.0; + maxDistance = 10.0; +}; + +datablock EffectProfile(BomberTurretFireEffect) +{ + effectname = "vehicles/bomber_turret_fire"; + minDistance = 5.0; + maxDistance = 10.0; +}; + +datablock EffectProfile(BomberTurretActivateEffect) +{ + effectname = "vehicles/bomber_turret_activate"; + minDistance = 5.0; + maxDistance = 10.0; +}; + +datablock EffectProfile(BomberTurretReloadEffect) +{ + effectname = "vehicles/bomber_turret_reload"; + minDistance = 5.0; + maxDistance = 10.0; +}; + +datablock EffectProfile(BomberTurretDryFireEffect) +{ + effectname = "vehicles/bomber_turret_dryfire"; + minDistance = 5.0; + maxDistance = 10.0; +}; + +datablock EffectProfile(BomberBombReloadEffect) +{ + effectname = "vehicles/bomber_bomb_reload"; + minDistance = 5.0; + maxDistance = 10.0; +}; + +datablock EffectProfile(BomberBombDryFireEffect) +{ + effectname = "vehicles/bomber_bomb_dryfire"; + minDistance = 5.0; + maxDistance = 10.0; +}; + +datablock EffectProfile(BomberBombFireEffect) +{ + effectname = "weapons/generic_throw"; + minDistance = 10.0; + maxDistance = 20.0; +}; + +datablock AudioProfile(BomberFlyerEngineSound) +{ + filename = "fx/vehicles/bomber_engine.wav"; + description = AudioDefaultLooping3d; + preload = true; + effect = BomberFlyerEngineEffect; +}; + +datablock AudioProfile(BomberFlyerThrustSound) +{ + filename = "fx/vehicles/bomber_boost.wav"; + description = AudioDefaultLooping3d; + preload = true; + effect = BomberFlyerThrustEffect; +}; + +datablock AudioProfile(FusionExpSound) +// Sound played when mortar impacts on target +{ + filename = "fx/powered/turret_mortar_explode.wav"; + description = "AudioBIGExplosion3d"; + preload = true; +}; + +datablock AudioProfile(BomberTurretFireSound) +{ + filename = "fx/vehicles/bomber_turret_fire.wav"; + description = AudioClose3d; + preload = true; + effect = BomberTurretFireEffect; +}; + +datablock AudioProfile(BomberTurretActivateSound) +{ + filename = "fx/vehicles/bomber_turret_activate.wav"; + description = AudioClose3d; + preload = true; + effect = BomberTurretActivateEffect; +}; + +datablock AudioProfile(BomberTurretReloadSound) +{ + filename = "fx/vehicles/bomber_turret_reload.wav"; + description = AudioClose3d; + preload = true; + effect = BomberTurretReloadEffect; +}; + +datablock AudioProfile(BomberTurretIdleSound) +{ + filename = "fx/misc/diagnostic_on.wav"; + description = ClosestLooping3d; + preload = true; +}; + +datablock AudioProfile(BomberTurretDryFireSound) +{ + filename = "fx/vehicles/bomber_turret_dryfire.wav"; + description = AudioClose3d; + preload = true; + effect = BomberTurretDryFireEffect; +}; + +datablock AudioProfile(BomberBombReloadSound) +{ + filename = "fx/vehicles/bomber_bomb_reload.wav"; + description = AudioClose3d; + preload = true; + effect = BomberBombReloadEffect; +}; + +datablock AudioProfile(BomberBombProjectileSound) +{ + filename = "fx/vehicles/bomber_bomb_projectile.wav"; + description = AudioDefaultLooping3d; + preload = true; + effect = BomberBombFireEffect; +}; + +datablock AudioProfile(BomberBombDryFireSound) +{ + filename = "fx/vehicles/bomber_bomb_dryfire.wav"; + description = AudioClose3d; + preload = true; + effect = BomberBombDryFireEffect; +}; + +datablock AudioProfile(BomberBombFireSound) +{ + filename = "fx/vehicles/bomber_bomb_reload.wav"; + description = AudioClose3d; + preload = true; + effect = BomberBombFireEffect; +}; + +datablock AudioProfile(BomberBombIdleSound) +{ + filename = "fx/misc/diagnostic_on.wav"; + description = ClosestLooping3d; + preload = true; +}; + +//************************************************************** +// VEHICLE CHARACTERISTICS +//************************************************************** + +datablock FlyingVehicleData(BomberFlyer) : BomberDamageProfile +{ + spawnOffset = "0 0 2"; + canControl = true; + catagory = "Vehicles"; + shapeFile = "vehicle_air_bomber.dts"; + multipassenger = true; + computeCRC = true; + + weaponNode = 1; + + debrisShapeName = "vehicle_air_bomber_debris.dts"; + debris = ShapeDebris; + renderWhenDestroyed = false; + + drag = 0.2; + density = 1.0; + + mountPose[0] = sitting; + mountPose[1] = sitting; + numMountPoints = 3; + isProtectedMountPoint[0] = true; + isProtectedMountPoint[1] = true; + isProtectedMountPoint[2] = true; + + cameraDefaultFov = 90.0; + cameraMinFov = 5.0; + cameraMaxFov = 120.0; + + cameraMaxDist = 22; + cameraOffset = 5; + cameraLag = 1.0; + explosion = LargeAirVehicleExplosion; + explosionDamage = 0.5; + explosionRadius = 5.0; + + maxDamage = 2.80; // Total health + destroyedLevel = 2.80; // Damage textures show up at this health level + + isShielded = true; + energyPerDamagePoint = 150; + maxEnergy = 400; // Afterburner and any energy weapon pool + minDrag = 60; // Linear Drag (eventually slows you down when not thrusting...constant drag) + rotationalDrag = 1800; // Angular Drag (dampens the drift after you stop moving the mouse...also tumble drag) + rechargeRate = 0.8; + + // Auto stabilize speed + maxAutoSpeed = 15; // Autostabilizer kicks in when less than this speed. (meters/second) + autoAngularForce = 1500; // Angular stabilizer force (this force levels you out when autostabilizer kicks in) + autoLinearForce = 300; // Linear stabilzer force (this slows you down when autostabilizer kicks in) + autoInputDamping = 0.95; // Dampen control input so you don't whack out at very slow speeds + + // Maneuvering + maxSteeringAngle = 5; // Max radiens you can rotate the wheel. Smaller number is more maneuverable. + horizontalSurfaceForce = 5; // Horizontal center "wing" (provides "bite" into the wind for climbing/diving and turning) + verticalSurfaceForce = 8; // Vertical center "wing" (controls side slip. lower numbers make MORE slide.) + maneuveringForce = 4700; // Horizontal jets (W,S,D,A key thrust) + steeringForce = 1100; // Steering jets (force applied when you move the mouse) + steeringRollForce = 300; // Steering jets (how much you heel over when you turn) + rollForce = 8; // Auto-roll (self-correction to right you after you roll/invert) + hoverHeight = 5; // Height off the ground at rest + createHoverHeight = 3; // Height off the ground when created + maxForwardSpeed = 85; // speed in which forward thrust force is no longer applied (meters/second) + + // Turbo Jet + jetForce = 3000; // Afterburner thrust (this is in addition to normal thrust) + minJetEnergy = 40.0; // Afterburner can't be used if below this threshhold. + jetEnergyDrain = 3.0; // Energy use of the afterburners (low number is less drain...can be fractional) + vertThrustMultiple = 3.0; + + dustEmitter = LargeVehicleLiftoffDustEmitter; + triggerDustHeight = 4.0; + dustHeight = 2.0; + + damageEmitter[0] = LightDamageSmoke; + damageEmitter[1] = HeavyDamageSmoke; + damageEmitter[2] = DamageBubbles; + damageEmitterOffset[0] = "3.0 -3.0 0.0 "; + damageEmitterOffset[1] = "-3.0 -3.0 0.0 "; + damageLevelTolerance[0] = 0.3; + damageLevelTolerance[1] = 0.7; + numDmgEmitterAreas = 2; + + // Rigid body + mass = 350; // Mass of the vehicle + bodyFriction = 0; // Don't mess with this. + bodyRestitution = 0.5; // When you hit the ground, how much you rebound. (between 0 and 1) + minRollSpeed = 0; // Don't mess with this. + softImpactSpeed = 20; // Sound hooks. This is the soft hit. + hardImpactSpeed = 25; // Sound hooks. This is the hard hit. + + // Ground Impact Damage (uses DamageType::Ground) + minImpactSpeed = 20; // If hit ground at speed above this then it's an impact. Meters/second + speedDamageScale = 0.060; + + // Object Impact Damage (uses DamageType::Impact) + collDamageThresholdVel = 25; + collDamageMultiplier = 0.020; + + // + minTrailSpeed = 15; // The speed your contrail shows up at. + trailEmitter = ContrailEmitter; + forwardJetEmitter = FlyerJetEmitter; + downJetEmitter = FlyerJetEmitter; + + // + jetSound = BomberFlyerThrustSound; + engineSound = BomberFlyerEngineSound; + softImpactSound = SoftImpactSound; + hardImpactSound = HardImpactSound; + //wheelImpactSound = WheelImpactSound; + + // + softSplashSoundVelocity = 15.0; + mediumSplashSoundVelocity = 20.0; + hardSplashSoundVelocity = 30.0; + exitSplashSoundVelocity = 10.0; + + exitingWater = VehicleExitWaterHardSound; + impactWaterEasy = VehicleImpactWaterSoftSound; + impactWaterMedium = VehicleImpactWaterMediumSound; + impactWaterHard = VehicleImpactWaterHardSound; + waterWakeSound = VehicleWakeHardSplashSound; + + minMountDist = 4; + + splashEmitter[0] = VehicleFoamDropletsEmitter; + splashEmitter[1] = VehicleFoamEmitter; + + shieldImpact = VehicleShieldImpact; + + cmdCategory = "Tactical"; + cmdIcon = CMDFlyingBomberIcon; + cmdMiniIconName = "commander/MiniIcons/com_bomber_grey"; + targetNameTag = 'Thundersword'; + targetTypeTag = 'Bomber'; + sensorData = VehiclePulseSensor; + + checkRadius = 7.1895; + observeParameters = "1 10 10"; + shieldEffectScale = "0.75 0.975 0.375"; + showPilotInfo = 1; +}; + +//************************************************************** +// WEAPONS +//************************************************************** + +//------------------------------------- +// BOMBER BELLY TURRET GUN (projectile) +//------------------------------------- + +datablock ShockwaveData(BomberFusionShockwave) +{ + width = 0.5; + numSegments = 13; + numVertSegments = 1; + velocity = 0.5; + acceleration = 2.0; + lifetimeMS = 900; + height = 0.1; + verticalCurve = 0.5; + + mapToTerrain = false; + renderBottom = false; + orientToNormal = true; + + texture[0] = "special/shockwave5"; + texture[1] = "special/gradient"; + texWrap = 3.0; + + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; + + colors[0] = "0.6 0.6 1.0 1.0"; + colors[1] = "0.6 0.3 1.0 0.5"; + colors[2] = "0.0 0.0 1.0 0.0"; +}; + +datablock ParticleData(BomberFusionExplosionParticle1) +{ + dragCoefficient = 2; + gravityCoefficient = 0.0; + inheritedVelFactor = 0.2; + constantAcceleration = -0.0; + lifetimeMS = 600; + lifetimeVarianceMS = 000; + textureName = "special/crescent4"; + colors[0] = "0.6 0.6 1.0 1.0"; + colors[1] = "0.6 0.3 1.0 1.0"; + colors[2] = "0.0 0.0 1.0 0.0"; + sizes[0] = 0.25; + sizes[1] = 0.5; + sizes[2] = 1.0; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; +}; + +datablock ParticleEmitterData(BomberFusionExplosionEmitter) +{ + ejectionPeriodMS = 7; + periodVarianceMS = 0; + ejectionVelocity = 2; + velocityVariance = 1.5; + ejectionOffset = 0.0; + thetaMin = 80; + thetaMax = 90; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + orientParticles = true; + lifetimeMS = 200; + particles = "BomberFusionExplosionParticle1"; +}; + +datablock ExplosionData(BomberFusionBoltExplosion) +{ + soundProfile = blasterExpSound; + shockwave = BomberFusionShockwave; + emitter[0] = BomberFusionExplosionEmitter; +}; + + +datablock LinearFlareProjectileData(BomberFusionBolt) +{ + projectileShapeName = ""; + directDamage = 0.35; + directDamageType = $DamageType::BellyTurret; + hasDamageRadius = false; + explosion = BomberFusionBoltExplosion; + sound = BlasterProjectileSound; + + dryVelocity = 200.0; + wetVelocity = 200.0; + velInheritFactor = 1.0; + fizzleTimeMS = 2000; + lifetimeMS = 3000; + explodeOnDeath = false; + reflectOnWaterImpactAngle = 0.0; + explodeOnWaterImpact = true; + deflectionOnWaterImpact = 0.0; + fizzleUnderwaterMS = -1; + + activateDelayMS = 100; + + numFlares = 0; + size = 0.15; + flareColor = "0.7 0.3 1.0"; + flareModTexture = "flaremod"; + flareBaseTexture = "flarebase"; +}; + +//------------------------------------- +// BOMBER BELLY TURRET CHARACTERISTICS +//------------------------------------- + +datablock TurretData(BomberTurret) : TurretDamageProfile +{ + className = VehicleTurret; + catagory = "Turrets"; + shapeFile = "turret_belly_base.dts"; + preload = true; + canControl = true; + cmdCategory = "Tactical"; + cmdIcon = CMDFlyingBomberIcon; + cmdMiniIconName = "commander/MiniIcons/com_bomber_grey"; + targetNameTag = 'Thundersword'; + targetTypeTag = 'Bomberturret'; + + mass = 1.0; // Not really relevant + repairRate = 0; + maxDamage = BomberFlyer.maxDamage; + destroyedLevel = BomberFlyer.destroyedLevel; + + thetaMin = 90; + thetaMax = 180; + + // capacitor + maxCapacitorEnergy = 250; + capacitorRechargeRate = 0.8; + + inheritEnergyFromMount = true; + firstPersonOnly = true; + useEyePoint = true; + numWeapons = 3; + + targetNameTag = 'Thundersword Belly'; + targetTypeTag = 'Turret'; +}; + +datablock TurretImageData(BomberTurretBarrel) +{ + shapeFile = "turret_belly_barrell.dts"; + mountPoint = 0; + + projectile = BomberFusionBolt; + projectileType = LinearFlareProjectile; + + usesEnergy = true; + useCapacitor = true; + useMountEnergy = true; + fireEnergy = 16.0; + minEnergy = 16.0; + + // Turret parameters + activationMS = 1000; + deactivateDelayMS = 1500; + thinkTimeMS = 200; + degPerSecTheta = 360; + degPerSecPhi = 360; + + attackRadius = 75; + + // State transitions + stateName[0] = "Activate"; + stateTransitionOnTimeout[0] = "WaitFire1"; + stateTimeoutValue[0] = 0.5; + stateSequence[0] = "Activate"; + stateSound[0] = BomberTurretActivateSound; + + stateName[1] = "WaitFire1"; + stateTransitionOnTriggerDown[1] = "Fire1"; + stateTransitionOnNoAmmo[1] = "NoAmmo1"; + + stateName[2] = "Fire1"; + stateTransitionOnTimeout[2] = "Reload1"; + stateTimeoutValue[2] = 0.13; + stateFire[2] = true; + stateRecoil[2] = LightRecoil; + stateAllowImageChange[2] = false; + stateSequence[2] = "Fire"; + stateScript[2] = "onFire"; + stateSound[2] = BomberTurretFireSound; + + stateName[3] = "Reload1"; + stateSequence[3] = "Reload"; + stateTimeoutValue[3] = 0.1; + stateAllowImageChange[3] = false; + stateTransitionOnTimeout[3] = "WaitFire2"; + stateTransitionOnNoAmmo[3] = "NoAmmo1"; + + stateName[4] = "NoAmmo1"; + stateTransitionOnAmmo[4] = "Reload1"; + // --------------------------------------------- + // z0dd - ZOD, 5/8/02. Incorrect parameter value + //stateSequence[4] = "NoAmmo"; + stateSequence[4] = "NoAmmo1"; + + stateTransitionOnTriggerDown[4] = "DryFire1"; + + stateName[5] = "DryFire1"; + stateSound[5] = BomberTurretDryFireSound; + stateTimeoutValue[5] = 0.5; + stateTransitionOnTimeout[5] = "NoAmmo1"; + + stateName[6] = "WaitFire2"; + stateTransitionOnTriggerDown[6] = "Fire2"; + // --------------------------------------------- + // z0dd - ZOD, 5/8/02. Incorrect parameter value + //stateTransitionOnNoAmmo[6] = "NoAmmo"; + stateTransitionOnNoAmmo[6] = "NoAmmo2"; + + stateName[7] = "Fire2"; + stateTransitionOnTimeout[7] = "Reload2"; + stateTimeoutValue[7] = 0.13; + stateScript[7] = "FirePair"; + + stateName[8] = "Reload2"; + stateSequence[8] = "Reload"; + stateTimeoutValue[8] = 0.1; + stateAllowImageChange[8] = false; + stateTransitionOnTimeout[8] = "WaitFire1"; + stateTransitionOnNoAmmo[8] = "NoAmmo2"; + + stateName[9] = "NoAmmo2"; + stateTransitionOnAmmo[9] = "Reload2"; + // --------------------------------------------- + // z0dd - ZOD, 5/8/02. Incorrect parameter value + //stateSequence[9] = "NoAmmo"; + stateSequence[9] = "NoAmmo2"; + + stateTransitionOnTriggerDown[9] = "DryFire2"; + + stateName[10] = "DryFire2"; + stateSound[10] = BomberTurretDryFireSound; + stateTimeoutValue[10] = 0.5; + stateTransitionOnTimeout[10] = "NoAmmo2"; + +}; + +datablock TurretImageData(BomberTurretBarrelPair) +{ + shapeFile = "turret_belly_barrelr.dts"; + mountPoint = 1; + + projectile = BomberFusionBolt; + projectileType = LinearFlareProjectile; + + usesEnergy = true; + useCapacitor = true; + useMountEnergy = true; + fireEnergy = 16.0; + minEnergy = 16.0; + + // Turret parameters + activationMS = 1000; + deactivateDelayMS = 1500; + thinkTimeMS = 200; + degPerSecTheta = 360; + degPerSecPhi = 360; + + attackRadius = 75; + + stateName[0] = "WaitFire"; + stateTransitionOnTriggerDown[0] = "Fire"; + + stateName[1] = "Fire"; + stateTransitionOnTimeout[1] = "StopFire"; + stateTimeoutValue[1] = 0.13; + stateFire[1] = true; + stateRecoil[1] = LightRecoil; + stateAllowImageChange[1] = false; + stateSequence[1] = "Fire"; + stateScript[1] = "onFire"; + stateSound[1] = BomberTurretFireSound; + + stateName[2] = "StopFire"; + stateTimeoutValue[2] = 0.1; + stateTransitionOnTimeout[2] = "WaitFire"; + stateScript[2] = "stopFire"; +}; + +datablock TurretImageData(AIAimingTurretBarrel) +{ + shapeFile = "turret_muzzlepoint.dts"; + mountPoint = 3; + + projectile = BomberFusionBolt; + + // Turret parameters + activationMS = 1000; + deactivateDelayMS = 1500; + thinkTimeMS = 200; + degPerSecTheta = 500; + degPerSecPhi = 800; + + attackRadius = 75; +}; + +//------------------------------------- +// BOMBER BOMB PROJECTILE +//------------------------------------- + +datablock BombProjectileData(BomberBomb) +{ + projectileShapeName = "bomb.dts"; + emitterDelay = -1; + directDamage = 0.0; + hasDamageRadius = true; + indirectDamage = 1.1; + damageRadius = 30; + radiusDamageType = $DamageType::BomberBombs; + kickBackStrength = 2500; + + explosion = "VehicleBombExplosion"; + velInheritFactor = 1.0; + + grenadeElasticity = 0.25; + grenadeFriction = 0.4; + armingDelayMS = 2000; + muzzleVelocity = 0.1; + drag = 0.3; + + minRotSpeed = "60.0 0.0 0.0"; + maxRotSpeed = "80.0 0.0 0.0"; + scale = "1.0 1.0 1.0"; + + sound = BomberBombProjectileSound; +}; + +//------------------------------------- +// BOMBER BOMB CHARACTERISTICS +//------------------------------------- + +datablock ItemData(BombAmmo) +{ + className = Ammo; + catagory = "Ammo"; + shapeFile = "repair_kit.dts"; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 1; + computeCRC = true; +}; + +datablock StaticShapeData(DropBombs) +{ + catagory = "Turrets"; + shapeFile = "bombers_eye.dts"; + maxDamage = 1.0; + disabledLevel = 0.6; + destroyedLevel = 0.8; +}; + +datablock TurretImageData(BomberBombImage) +{ + shapeFile = "turret_muzzlepoint.dts"; + offset = "2 -4 -0.5"; + mountPoint = 10; + + projectile = BomberBomb; + projectileType = BombProjectile; + usesEnergy = true; + useMountEnergy = true; + useCapacitor = true; + + fireEnergy = 53.0; + minEnergy = 53.0; + + + stateName[0] = "Activate"; + stateTransitionOnTimeout[0] = "WaitFire1"; + stateTimeoutValue[0] = 0.5; + stateSequence[0] = "Activate"; + + stateName[1] = "WaitFire1"; + stateTransitionOnTriggerDown[1] = "Fire1"; + stateTransitionOnNoAmmo[1] = "NoAmmo1"; + + stateName[2] = "Fire1"; + stateTransitionOnTimeout[2] = "Reload1"; + stateTimeoutValue[2] = 0.32; + stateFire[2] = true; + stateAllowImageChange[2] = false; + stateSequence[2] = "Fire"; + stateScript[2] = "onFire"; + stateSound[2] = BomberBombFireSound; + + stateName[3] = "Reload1"; + stateSequence[3] = "Reload"; + stateTimeoutValue[3] = 0.1; + stateAllowImageChange[3] = false; + stateTransitionOnTimeout[3] = "WaitFire2"; + stateTransitionOnNoAmmo[3] = "NoAmmo1"; + + stateName[4] = "NoAmmo1"; + stateTransitionOnAmmo[4] = "Reload1"; + // --------------------------------------------- + // z0dd - ZOD, 5/8/02. Incorrect parameter value + //stateSequence[4] = "NoAmmo"; + stateSequence[4] = "NoAmmo1"; + + stateTransitionOnTriggerDown[4] = "DryFire1"; + + stateName[5] = "DryFire1"; + stateSound[5] = BomberBombDryFireSound; + stateTimeoutValue[5] = 0.5; + stateTransitionOnTimeout[5] = "NoAmmo1"; + + stateName[6] = "WaitFire2"; + stateTransitionOnTriggerDown[6] = "Fire2"; + // --------------------------------------------- + // z0dd - ZOD, 5/8/02. Incorrect parameter value + //stateTransitionOnNoAmmo[6] = "NoAmmo"; + stateTransitionOnNoAmmo[6] = "NoAmmo2"; + + stateName[7] = "Fire2"; + stateTransitionOnTimeout[7] = "Reload2"; + stateTimeoutValue[7] = 0.32; + stateScript[7] = "FirePair"; + + stateName[8] = "Reload2"; + stateSequence[8] = "Reload"; + stateTimeoutValue[8] = 0.1; + stateAllowImageChange[8] = false; + stateTransitionOnTimeout[8] = "WaitFire1"; + stateTransitionOnNoAmmo[8] = "NoAmmo2"; + + stateName[9] = "NoAmmo2"; + stateTransitionOnAmmo[9] = "Reload2"; + // --------------------------------------------- + // z0dd - ZOD, 5/8/02. Incorrect parameter value + //stateSequence[9] = "NoAmmo"; + stateSequence[9] = "NoAmmo2"; + + stateTransitionOnTriggerDown[9] = "DryFire2"; + + stateName[10] = "DryFire2"; + stateSound[10] = BomberBombDryFireSound; + stateTimeoutValue[10] = 0.5; + stateTransitionOnTimeout[10] = "NoAmmo2"; +}; + +datablock TurretImageData(BomberBombPairImage) +{ + shapeFile = "turret_muzzlepoint.dts"; + offset = "-2 -4 -0.5"; + mountPoint = 10; + + projectile = BomberBomb; + projectileType = BombProjectile; + usesEnergy = true; + useMountEnergy = true; + useCapacitor = true; + fireEnergy = 53.0; + minEnergy = 53.0; + + stateName[0] = "WaitFire"; + stateTransitionOnTriggerDown[0] = "Fire"; + + stateName[1] = "Fire"; + stateTransitionOnTimeout[1] = "StopFire"; + stateTimeoutValue[1] = 0.13; + stateFire[1] = true; + stateAllowImageChange[1] = false; + stateSequence[1] = "Fire"; + stateScript[1] = "onFire"; + stateSound[1] = BomberBombFireSound; + + stateName[2] = "StopFire"; + stateTimeoutValue[2] = 0.1; + stateTransitionOnTimeout[2] = "WaitFire"; + stateScript[2] = "stopFire"; + +}; + +//************************************************************** +// WEAPONS SPECIAL EFFECTS +//************************************************************** + +//------------------------------------- +// BOMBER BELLY TURRET GUN (explosion) +//------------------------------------- + +datablock ParticleData(FusionExplosionParticle) +{ + dragCoefficient = 2; + gravityCoefficient = 0.2; + inheritedVelFactor = 0.2; + constantAcceleration = 0.0; + lifetimeMS = 750; + lifetimeVarianceMS = 150; + textureName = "particleTest"; + colors[0] = "0.56 0.36 0.26 1.0"; + colors[1] = "0.56 0.36 0.26 0.0"; + sizes[0] = 1; + sizes[1] = 2; +}; + +datablock ParticleEmitterData(FusionExplosionEmitter) +{ + ejectionPeriodMS = 7; + periodVarianceMS = 0; + ejectionVelocity = 12; + velocityVariance = 1.75; + ejectionOffset = 0.0; + thetaMin = 0; + thetaMax = 60; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + particles = "FusionExplosionParticle"; +}; + +datablock ExplosionData(FusionBoltExplosion) +{ + explosionShape = "effect_plasma_explosion.dts"; + soundProfile = FusionExpSound; + particleEmitter = FusionExplosionEmitter; + particleDensity = 250; + particleRadius = 1.25; + faceViewer = true; +}; + +//-------------------------------------------------------------------------- +// BOMBER TARGETING LASER +//-------------------------------------------------------------------------- + +datablock AudioProfile(BomberTargetingSwitchSound) +{ + filename = "fx/weapons/generic_switch.wav"; + description = AudioClosest3d; + preload = true; +}; + +datablock AudioProfile(BomberTargetingPaintSound) +{ + filename = "fx/weapons/targetinglaser_paint.wav"; + description = CloseLooping3d; + preload = true; +}; + +//-------------------------------------- +// BOMBER TARGETING PROJECTILE +//-------------------------------------- +datablock TargetProjectileData(BomberTargeter) +{ + directDamage = 0.0; + hasDamageRadius = false; + indirectDamage = 0.0; + damageRadius = 0.0; + velInheritFactor = 1.0; + + maxRifleRange = 1000; + beamColor = "0.1 1.0 0.1"; + + startBeamWidth = 0.20; + pulseBeamWidth = 0.15; + beamFlareAngle = 3.0; + minFlareSize = 0.0; + maxFlareSize = 400.0; + pulseSpeed = 6.0; + pulseLength = 0.150; + + textureName[0] = "special/nonlingradient"; + textureName[1] = "special/flare"; + textureName[2] = "special/pulse"; + textureName[3] = "special/expFlare"; +}; + +//------------------------------------- +// BOMBER TARGETING CHARACTERISTICS +//------------------------------------- +datablock ShapeBaseImageData(BomberTargetingImage) +{ + className = WeaponImage; + + shapeFile = "turret_muzzlepoint.dts"; + offset = "0 -0.04 -0.01"; + mountPoint = 2; + + projectile = BomberTargeter; + projectileType = TargetProjectile; + deleteLastProjectile = true; + + usesEnergy = true; + minEnergy = 3; + + stateName[0] = "Activate"; + stateSequence[0] = "Activate"; + stateSound[0] = BomberTargetingSwitchSound; + stateTimeoutValue[0] = 0.5; + stateTransitionOnTimeout[0] = "ActivateReady"; + + stateName[1] = "ActivateReady"; + stateTransitionOnAmmo[1] = "Ready"; + stateTransitionOnNoAmmo[1] = "NoAmmo"; + + stateName[2] = "Ready"; + stateTransitionOnNoAmmo[2] = "NoAmmo"; + stateTransitionOnTriggerDown[2] = "Fire"; + + stateName[3] = "Fire"; + stateEnergyDrain[3] = 3; + stateFire[3] = true; + stateAllowImageChange[3] = false; + stateScript[3] = "onFire"; + stateTransitionOnTriggerUp[3] = "Deconstruction"; + stateTransitionOnNoAmmo[3] = "Deconstruction"; + stateSound[3] = BomberTargetingPaintSound; + + stateName[4] = "NoAmmo"; + stateTransitionOnAmmo[4] = "Ready"; + + stateName[5] = "Deconstruction"; + stateTransitionOnTimeout[5] = "ActivateReady"; + stateTimeoutValue[5] = 0.05; +}; + +function BomberTargetingImage::onFire(%data,%obj,%slot) +{ + %bomber = %obj.getObjectMount(); + if(%bomber.beacon) + { + %bomber.beacon.delete(); + %bomber.beacon = ""; + } + %p = Parent::onFire(%data, %obj, %slot); + %p.setTarget(%obj.team); +} + +function BomberTargetingImage::deconstruct(%data, %obj, %slot) +{ + %pos = %obj.lastProjectile.getTargetPoint(); + %bomber = %obj.getObjectMount(); + + if(%bomber.beacon) + { + %bomber.beacon.delete(); + %bomber.beacon = ""; + } + %bomber.beacon = new BeaconObject() { + dataBlock = "BomberBeacon"; + beaconType = "vehicle"; + position = %pos; + }; + + %bomber.beacon.playThread($AmbientThread, "ambient"); + %bomber.beacon.team = %bomber.team; + %bomber.beacon.sourceObject = %bomber; + + // give it a team target + %bomber.beacon.setTarget(%bomber.team); + MissionCleanup.add(%bomber.beacon); + + Parent::deconstruct(%data, %obj, %slot); +} + +//------------------------------------- +// BOMBER BEACON +//------------------------------------- +datablock StaticShapeData(BomberBeacon) +{ + shapeFile = "turret_muzzlepoint.dts"; + targetNameTag = 'beacon'; + isInvincible = true; + + dynamicType = $TypeMasks::SensorObjectType; +}; diff --git a/scripts/vehicles/vehicle_escapepod.cs b/scripts/vehicles/vehicle_escapepod.cs new file mode 100644 index 0000000..1389234 --- /dev/null +++ b/scripts/vehicles/vehicle_escapepod.cs @@ -0,0 +1,138 @@ +// Escape Pod + +datablock HoverVehicleData(EscapePodVehicle) : WildcatDamageProfile { + spawnOffset = "0 0 1"; + canControl = false; + floatingGravMag = 2; // 3.5; + + catagory = "Vehicles"; + shapeFile = "vehicle_grav_scout.dts"; + computeCRC = true; + + debrisShapeName = "vehicle_grav_scout_debris.dts"; + debris = ShapeDebris; + renderWhenDestroyed = false; + + drag = 0.0; + density = 0.9; + + mountPose[0] = sitting; + cameraMaxDist = 5.0; + cameraOffset = 0.7; + cameraLag = 0.5; + numMountPoints = 1; + isProtectedMountPoint[0] = true; + explosion = VehicleExplosion; + explosionDamage = 0; // 0.5; + explosionRadius = 0; // 5.0; + + lightOnly = 0; + + maxDamage = 0.60; + destroyedLevel = 0.60; + + isShielded = true; + rechargeRate = 0.7; + energyPerDamagePoint = 75; + maxEnergy = 150; + minJetEnergy = 160; // disable? + jetEnergyDrain = 1.3; + + // Rigid Body + mass = 100; + bodyFriction = 0.1; + bodyRestitution = 0.5; + softImpactSpeed = 20; // Play SoftImpact Sound + hardImpactSpeed = 28; // Play HardImpact Sound + + // Ground Impact Damage (uses DamageType::Ground) + minImpactSpeed = 29; + speedDamageScale = 0.010; + + // Object Impact Damage (uses DamageType::Impact) + collDamageThresholdVel = 23; + collDamageMultiplier = 0.030; + + dragForce = 25 / 45.0; + vertFactor = 0.0; + floatingThrustFactor = 0.001; // 0.35; + + mainThrustForce = 0.001; + reverseThrustForce = 0.001; + strafeThrustForce = 0.001; + turboFactor = 0.001; + + brakingForce = 25; + brakingActivationSpeed = 20; + + stabLenMin = 2.25; + stabLenMax = 3.75; + stabSpringConstant = 30; + stabDampingConstant = 16; + + gyroDrag = 16; + normalForce = 10; + restorativeForce = 5; + steeringForce = 0.001; + rollForce = 0.001; + pitchForce = 0.001; + + dustEmitter = VehicleLiftoffDustEmitter; + triggerDustHeight = 2.5; + dustHeight = 1.0; + dustTrailEmitter = TireEmitter; + dustTrailOffset = "0.0 -1.0 0.5"; + triggerTrailHeight = 3.6; + dustTrailFreqMod = 15.0; + +// jetSound = ScoutSqueelSound; +// engineSound = ScoutEngineSound; +// floatSound = ScoutThrustSound; + softImpactSound = GravSoftImpactSound; + hardImpactSound = HardImpactSound; + + // + softSplashSoundVelocity = 10.0; + mediumSplashSoundVelocity = 20.0; + hardSplashSoundVelocity = 30.0; + exitSplashSoundVelocity = 10.0; + + exitingWater = VehicleExitWaterSoftSound; + impactWaterEasy = VehicleImpactWaterSoftSound; + impactWaterMedium = VehicleImpactWaterSoftSound; + impactWaterHard = VehicleImpactWaterMediumSound; + waterWakeSound = VehicleWakeSoftSplashSound; + + minMountDist = 4; + + damageEmitter[0] = SmallLightDamageSmoke; + damageEmitter[1] = SmallHeavyDamageSmoke; + damageEmitter[2] = DamageBubbles; + damageEmitterOffset[0] = "0.0 -1.5 0.5 "; + damageLevelTolerance[0] = 0.3; + damageLevelTolerance[1] = 0.7; + numDmgEmitterAreas = 1; + + splashEmitter[0] = VehicleFoamDropletsEmitter; + splashEmitter[1] = VehicleFoamEmitter; + + shieldImpact = VehicleShieldImpact; + +// forwardJetEmitter = WildcatJetEmitter; + + cmdCategory = Tactical; + cmdIcon = CMDHoverScoutIcon; + cmdMiniIconName = "commander/MiniIcons/com_landscout_grey"; + targetNameTag = 'Escape'; + targetTypeTag = 'Pod'; + sensorData = VehiclePulseSensor; + + checkRadius = 1.7785; + observeParameters = "1 10 10"; + + runningLight[0] = WildcatLight1; + runningLight[1] = WildcatLight2; + runningLight[2] = WildcatLight3; + + shieldEffectScale = "0.9375 1.125 0.6"; +}; diff --git a/scripts/vehicles/vehicle_havoc.cs b/scripts/vehicles/vehicle_havoc.cs new file mode 100644 index 0000000..75b5298 --- /dev/null +++ b/scripts/vehicles/vehicle_havoc.cs @@ -0,0 +1,226 @@ +//************************************************************** +// HAVOC HEAVY TRANSPORT FLIER +//************************************************************** +//************************************************************** +// SOUNDS +//************************************************************** +datablock EffectProfile(HAPCFlyerEngineEffect) +{ + effectname = "vehicles/htransport_thrust"; + minDistance = 5.0; + maxDistance = 10.0; +}; + +datablock EffectProfile(HAPCFlyerThrustEffect) +{ + effectname = "vehicles/htransport_boost"; + minDistance = 5.0; + maxDistance = 10.0; +}; + +datablock AudioProfile(HAPCFlyerEngineSound) +{ + filename = "fx/vehicles/htransport_thrust.wav"; + description = AudioDefaultLooping3d; + effect = HAPCFlyerEngineEffect; +}; + +datablock AudioProfile(HAPCFlyerThrustSound) +{ + filename = "fx/vehicles/htransport_boost.wav"; + description = AudioDefaultLooping3d; + effect = HAPCFlyerThrustEffect; +}; + +//************************************************************** +// VEHICLE CHARACTERISTICS +//************************************************************** + +datablock FlyingVehicleData(HAPCFlyer) : HavocDamageProfile +{ + spawnOffset = "0 0 6"; + renderWhenDestroyed = false; + + catagory = "Vehicles"; + shapeFile = "vehicle_air_hapc.dts"; + multipassenger = true; + computeCRC = true; + + + debrisShapeName = "vehicle_air_hapc_debris.dts"; + debris = ShapeDebris; + + drag = 0.2; + density = 1.0; + + mountPose[0] = sitting; +// mountPose[1] = sitting; + numMountPoints = 6; + isProtectedMountPoint[0] = true; + isProtectedMountPoint[1] = true; + isProtectedMountPoint[2] = true; + isProtectedMountPoint[3] = true; + isProtectedMountPoint[4] = true; + isProtectedMountPoint[5] = true; + canControl = true; + cameraMaxDist = 17; + cameraOffset = 2; + cameraLag = 8.5; + explosion = LargeAirVehicleExplosion; + explosionDamage = 0.5; + explosionRadius = 5.0; + + maxDamage = 3.50; + destroyedLevel = 3.50; + + isShielded = true; + rechargeRate = 0.8; + energyPerDamagePoint = 200; + maxEnergy = 550; + minDrag = 100; // Linear Drag + rotationalDrag = 2700; // Anguler Drag + + // Auto stabilize speed + maxAutoSpeed = 10; + autoAngularForce = 3000; // Angular stabilizer force + autoLinearForce = 450; // Linear stabilzer force + autoInputDamping = 0.95; // + + // Maneuvering + maxSteeringAngle = 8; + horizontalSurfaceForce = 10; // Horizontal center "wing" + verticalSurfaceForce = 10; // Vertical center "wing" + maneuveringForce = 6000; // Horizontal jets + steeringForce = 1000; // Steering jets + steeringRollForce = 400; // Steering jets + rollForce = 12; // Auto-roll + hoverHeight = 8; // Height off the ground at rest + createHoverHeight = 6; // Height off the ground when created + maxForwardSpeed = 71; // speed in which forward thrust force is no longer applied (meters/second) + + // Turbo Jet + jetForce = 5000; + minJetEnergy = 55; + jetEnergyDrain = 3.6; + vertThrustMultiple = 3.0; + + + dustEmitter = LargeVehicleLiftoffDustEmitter; + triggerDustHeight = 4.0; + dustHeight = 2.0; + + damageEmitter[0] = LightDamageSmoke; + damageEmitter[1] = HeavyDamageSmoke; + damageEmitter[2] = DamageBubbles; + damageEmitterOffset[0] = "3.0 -3.0 0.0 "; + damageEmitterOffset[1] = "-3.0 -3.0 0.0 "; + damageLevelTolerance[0] = 0.3; + damageLevelTolerance[1] = 0.7; + numDmgEmitterAreas = 2; + + // Rigid body + mass = 550; + bodyFriction = 0; + bodyRestitution = 0.3; + minRollSpeed = 0; + softImpactSpeed = 12; // Sound hooks. This is the soft hit. + hardImpactSpeed = 15; // Sound hooks. This is the hard hit. + + // Ground Impact Damage (uses DamageType::Ground) + minImpactSpeed = 25; // If hit ground at speed above this then it's an impact. Meters/second + speedDamageScale = 0.060; + + // Object Impact Damage (uses DamageType::Impact) + collDamageThresholdVel = 28; + collDamageMultiplier = 0.020; + + // + minTrailSpeed = 15; + trailEmitter = ContrailEmitter; + forwardJetEmitter = FlyerJetEmitter; + downJetEmitter = FlyerJetEmitter; + + // + jetSound = HAPCFlyerThrustSound; + engineSound = HAPCFlyerEngineSound; + softImpactSound = SoftImpactSound; + hardImpactSound = HardImpactSound; + //wheelImpactSound = WheelImpactSound; + + // + softSplashSoundVelocity = 5.0; + mediumSplashSoundVelocity = 8.0; + hardSplashSoundVelocity = 12.0; + exitSplashSoundVelocity = 8.0; + + exitingWater = VehicleExitWaterHardSound; + impactWaterEasy = VehicleImpactWaterSoftSound; + impactWaterMedium = VehicleImpactWaterMediumSound; + impactWaterHard = VehicleImpactWaterHardSound; + waterWakeSound = VehicleWakeHardSplashSound; + + minMountDist = 4; + + splashEmitter[0] = VehicleFoamDropletsEmitter; + splashEmitter[1] = VehicleFoamEmitter; + + shieldImpact = VehicleShieldImpact; + + cmdCategory = "Tactical"; + cmdIcon = CMDFlyingHAPCIcon; + cmdMiniIconName = "commander/MiniIcons/com_hapc_grey"; + targetNameTag = 'Havoc'; + targetTypeTag = 'Heavy Transport'; + sensorData = VehiclePulseSensor; + + checkRadius = 7.8115; + observeParameters = "1 15 15"; + + stuckTimerTicks = 32; // If the hapc spends more than 1 sec in contact with something + stuckTimerAngle = 80; // with a > 80 deg. pitch, BOOM! + + shieldEffectScale = "1.0 0.9375 0.45"; +}; + +function HAPCFlyer::hasDismountOverrides(%data, %obj) +{ + return true; +} + +function HAPCFlyer::getDismountOverride(%data, %obj, %mounted) +{ + %node = -1; + for (%i = 0; %i < %data.numMountPoints; %i++) + { + if (%obj.getMountNodeObject(%i) == %mounted) + { + %node = %i; + break; + } + } + if (%node == -1) + { + warning("Couldn't find object mount point"); + return "0 0 1"; + } + + if (%node == 3 || %node == 2) + { + return "-1 0 1"; + } + else if (%node == 5 || %node == 4) + { + return "1 0 1"; + } + else + { + return "0 0 1"; + } +} + +//************************************************************** +// WEAPONS +//************************************************************** + + + diff --git a/scripts/vehicles/vehicle_mpb.cs b/scripts/vehicles/vehicle_mpb.cs new file mode 100644 index 0000000..06a3247 --- /dev/null +++ b/scripts/vehicles/vehicle_mpb.cs @@ -0,0 +1,304 @@ +//************************************************************** +// JERICHO FORWARD BASE (Mobile Point Base) +//************************************************************** +//************************************************************** +// SOUNDS +//************************************************************** +datablock EffectProfile(MPBEngineEffect) +{ + effectname = "vehicles/mpb_thrust"; + minDistance = 5.0; + maxDistance = 10.0; +}; + +datablock EffectProfile(MPBThrustEffect) +{ + effectname = "vehicles/mpb_boost"; + minDistance = 5.0; + maxDistance = 10.0; +}; + +datablock AudioProfile(MPBEngineSound) +{ + filename = "fx/vehicles/mpb_thrust.wav"; + description = AudioDefaultLooping3d; + preload = true; + effect = MPBEngineEffect; +}; + +datablock AudioProfile(MPBThrustSound) +{ + filename = "fx/vehicles/mpb_boost.wav"; + description = AudioDefaultLooping3d; + preload = true; + effect = MPBThrustEffect; +}; + +datablock AudioProfile(MobileBaseDeploySound) +{ + filename = "fx/vehicles/MPB_deploy.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(MobileBaseUndeploySound) +{ + filename = "fx/vehicles/MPB_undeploy_turret.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(MobileBaseTurretDeploySound) +{ + filename = "fx/vehicles/MPB_deploy_turret.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(MobileBaseTurretUndeploySound) +{ + filename = "fx/vehicles/MPB_undeploy_turret.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(MobileBaseStationDeploySound) +{ + filename = "fx/vehicles/MPB_deploy_station.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(MobileBaseStationUndeploySound) +{ + filename = "fx/vehicles/MPB_close_lid.wav"; + description = AudioClose3d; + preload = true; +}; + + +//************************************************************** +// LIGHTS +//************************************************************** +datablock RunningLightData(MPBLight1) +{ + pointSize = 3.0; + pointColor = "1.0 1.0 1.0 0.3"; + pointNodeName = "Headlight_node01"; + texture = "special/expFlare"; +}; + +datablock RunningLightData(MPBLight2) +{ + pointSize = 3.0; + pointColor = "1.0 1.0 1.0 0.3"; + pointNodeName = "Headlight_node02"; + texture = "special/expFlare"; +}; + + +//************************************************************** +// VEHICLE CHARACTERISTICS +//************************************************************** +datablock SensorData(MPBDeployedSensor) : VehiclePulseSensor +{ + jams = true; + jamsOnlyGroup = true; + jamsUsingLOS = false; + jamRadius = 50; +}; + +datablock WheeledVehicleData(MobileBaseVehicle) : MPBDamageProfile +{ + spawnOffset = "0 0 1.0"; + renderWhenDestroyed = false; + canControl = true; + catagory = "Vehicles"; + shapeFile = "vehicle_land_mpbase.dts"; + multipassenger = false; + computeCRC = true; + + debrisShapeName = "vehicle_land_mpbase_debris.dts"; + debris = ShapeDebris; + + drag = 0.0; + density = 20.0; + + mountPose[0] = sitting; + numMountPoints = 1; + isProtectedMountPoint[0] = true; + + cantAbandon = 1; + cantTeamSwitch = 1; + + cameraMaxDist = 20; + cameraOffset = 6; + cameraLag = 1.5; + explosion = LargeGroundVehicleExplosion; + explosionDamage = 0.5; + explosionRadius = 5.0; + + maxSteeringAngle = 0.3; // 20 deg. + + // Used to test if the station can deploy + stationPoints[1] = "-2.3 -7.38703 -0.65"; + stationPoints[2] = "-2.3 -11.8 -0.65"; + stationPoints[3] = "0 -7.38703 -0.65"; + stationPoints[4] = "0 -11.8 -0.65"; + stationPoints[5] = "2.3 -7.38703 -0.65"; + stationPoints[6] = "2.3 -11.8 -0.65"; + + // Rigid Body + mass = 2000; + bodyFriction = 0.8; + bodyRestitution = 0.5; + minRollSpeed = 3; + gyroForce = 400; + gyroDamping = 0.3; + stabilizerForce = 10; + minDrag = 10; + softImpactSpeed = 15; // Play SoftImpact Sound + hardImpactSpeed = 25; // Play HardImpact Sound + + // Ground Impact Damage (uses DamageType::Ground) + minImpactSpeed = 12; + speedDamageScale = 0.060; + + // Object Impact Damage (uses DamageType::Impact) + collDamageThresholdVel = 18; + collDamageMultiplier = 0.070; + + // Engine + engineTorque = 7.0 * 745; + breakTorque = 7.0 * 745; + maxWheelSpeed = 20; + + // Springs + springForce = 8000; + springDamping = 1300; + antiSwayForce = 6000; + staticLoadScale = 2; + + // Tires + tireRadius = 1.6; + tireFriction = 10.0; + tireRestitution = 0.5; + tireLateralForce = 3000; + tireLateralDamping = 400; + tireLateralRelaxation = 1; + tireLongitudinalForce = 12000; + tireLongitudinalDamping = 600; + tireLongitudinalRelaxation = 1; + tireEmitter = TireEmitter; + + // + maxDamage = 3.85; + destroyedLevel = 3.85; + + isShielded = true; + energyPerDamagePoint = 125; + maxEnergy = 600; + jetForce = 2800; + minJetEnergy = 60; + jetEnergyDrain = 2.75; + rechargeRate = 1.0; + + jetSound = MPBThrustSound; + engineSound = MPBEngineSound; + squeelSound = AssaultVehicleSkid; + softImpactSound = GravSoftImpactSound; + hardImpactSound = HardImpactSound; + //wheelImpactSound = WheelImpactSound; + + // + softSplashSoundVelocity = 5.0; + mediumSplashSoundVelocity = 8.0; + hardSplashSoundVelocity = 12.0; + exitSplashSoundVelocity = 8.0; + + exitingWater = VehicleExitWaterSoftSound; + impactWaterEasy = VehicleImpactWaterSoftSound; + impactWaterMedium = VehicleImpactWaterMediumSound; + impactWaterHard = VehicleImpactWaterHardSound; + waterWakeSound = VehicleWakeMediumSplashSound; + + minMountDist = 3; + + damageEmitter[0] = LightDamageSmoke; + damageEmitter[1] = HeavyDamageSmoke; + damageEmitter[2] = DamageBubbles; + damageEmitterOffset[0] = "3.0 0.5 0.0 "; + damageEmitterOffset[1] = "-3.0 0.5 0.0 "; + damageLevelTolerance[0] = 0.3; + damageLevelTolerance[1] = 0.7; + numDmgEmitterAreas = 2; + + splashEmitter[0] = VehicleFoamDropletsEmitter; + splashEmitter[1] = VehicleFoamEmitter; + + shieldImpact = VehicleShieldImpact; + + cmdCategory = "Tactical"; + cmdIcon = CMDGroundMPBIcon; + cmdMiniIconName = "commander/MiniIcons/com_mpb_grey"; + targetNameTag = 'Jericho'; + targetTypeTag = 'MPB'; + sensorData = VehiclePulseSensor; + + checkRadius = 7.5225; + + observeParameters = "1 12 12"; + + runningLight[0] = MPBLight1; + runningLight[1] = MPBLight2; + + shieldEffectScale = "0.85 1.2 0.7"; +}; + +//************************************************************** +// WEAPONS +//************************************************************** + +datablock SensorData(MPBTurretMissileSensor) +{ + detects = true; + detectsUsingLOS = true; + detectsPassiveJammed = false; + detectsActiveJammed = false; + detectsCloaked = false; + detectionPings = true; + detectRadius = 200; +}; + +datablock TurretData(MobileTurretBase) +{ + className = VehicleTurret; + catagory = "Turrets"; + shapeFile = "turret_base_mpb.dts"; + preload = true; + + mass = 1.0; // Not really relevant + + maxDamage = MobileBaseVehicle.maxDamage; + destroyedLevel = MobileBaseVehicle.destroyedLevel; + + thetaMin = 15; + thetaMax = 140; + + energyPerDamagePoint = 33; + inheritEnergyFromMount = true; + firstPersonOnly = true; + + sensorColor = "0 212 45"; + sensorData = MPBTurretMissileSensor; + sensorRadius = MPBTurretMissileSensor.detectRadius; + cmdCategory = "Tactical"; + cmdMiniIconName = "commander/MiniIcons/com_turret_grey"; + targetNameTag = 'Jericho'; + targetTypeTag = 'Turret'; + + canControl = true; +}; + + + diff --git a/scripts/vehicles/vehicle_shrike.cs b/scripts/vehicles/vehicle_shrike.cs new file mode 100644 index 0000000..fe868c1 --- /dev/null +++ b/scripts/vehicles/vehicle_shrike.cs @@ -0,0 +1,344 @@ +//************************************************************** +// SHRIKE SCOUT FLIER +//************************************************************** +//************************************************************** +// SOUNDS +//************************************************************** +datablock EffectProfile(ScoutFlyerThrustEffect) +{ + effectname = "vehicles/shrike_boost"; + minDistance = 5.0; + maxDistance = 10.0; +}; + +datablock EffectProfile(ScoutFlyerEngineEffect) +{ + effectname = "vehicles/shrike_engine"; + minDistance = 5.0; + maxDistance = 10.0; +}; + +datablock EffectProfile(ShrikeBlasterFireEffect) +{ + effectname = "vehicles/shrike_blaster"; + minDistance = 5.0; + maxDistance = 10.0; +}; + +datablock AudioProfile(ScoutFlyerThrustSound) +{ + filename = "fx/vehicles/shrike_boost.wav"; + description = AudioDefaultLooping3d; + preload = true; + effect = ScoutFlyerThrustEffect; +}; + +datablock AudioProfile(ScoutFlyerEngineSound) +{ + filename = "fx/vehicles/shrike_engine.wav"; + description = AudioDefaultLooping3d; + preload = true; +}; + +datablock AudioProfile(ShrikeBlasterFire) +{ + filename = "fx/vehicles/shrike_blaster.wav"; + description = AudioDefault3d; + preload = true; + effect = ScoutFlyerEngineEffect; +}; + +datablock AudioProfile(ShrikeBlasterProjectile) +{ + filename = "fx/weapons/shrike_blaster_projectile.wav"; + description = ProjectileLooping3d; + preload = true; + effect = ShrikeBlasterFireEffect; +}; + +datablock AudioProfile(ShrikeBlasterDryFireSound) +{ + filename = "fx/weapons/chaingun_dryfire.wav"; + description = AudioClose3d; + preload = true; +}; + +//************************************************************** +// LIGHTS +//************************************************************** +datablock RunningLightData(ShrikeLight1) +{ + type = 1; + radius = 2.0; + length = 3.0; + color = "1.0 1.0 1.0 1.0"; + direction = "0.0 1.0 -1.0 "; + offset = "0.0 0.0 -0.5"; + texture = "special/lightcone04"; +}; + +datablock RunningLightData(ShrikeLight2) +{ + radius = 1.5; + color = "1.0 1.0 1.0 0.3"; + direction = "0.0 0.0 -1.0"; + offset = "0.0 0.8 -1.2"; + texture = "special/headlight4"; +}; + +//************************************************************** +// VEHICLE CHARACTERISTICS +//************************************************************** + +datablock FlyingVehicleData(ScoutFlyer) : ShrikeDamageProfile +{ + spawnOffset = "0 0 2"; + canControl = true; + catagory = "Vehicles"; + shapeFile = "vehicle_air_scout.dts"; + multipassenger = true; + computeCRC = true; + + debrisShapeName = "vehicle_air_scout_debris.dts"; + debris = ShapeDebris; + renderWhenDestroyed = false; + + drag = 0.15; + density = 1.0; + + canWarp = 1; + + mountPose[0] = sitting; + numMountPoints = 2; + isProtectedMountPoint[0] = true; + isProtectedMountPoint[1] = true; + cameraMaxDist = 15; + cameraOffset = 2.5; + cameraLag = 0.9; + explosion = VehicleExplosion; + explosionDamage = 0.5; + explosionRadius = 5.0; + + maxDamage = 1.40; + destroyedLevel = 1.40; + + isShielded = true; + energyPerDamagePoint = 160; + maxEnergy = 280; // Afterburner and any energy weapon pool + rechargeRate = 0.8; + + minDrag = 30; // Linear Drag (eventually slows you down when not thrusting...constant drag) + rotationalDrag = 900; // Anguler Drag (dampens the drift after you stop moving the mouse...also tumble drag) + + maxAutoSpeed = 5; // Autostabilizer kicks in when less than this speed. (meters/second) + autoAngularForce = 50; // Angular stabilizer force (this force levels you out when autostabilizer kicks in) + autoLinearForce = 300; // Linear stabilzer force (this slows you down when autostabilizer kicks in) + autoInputDamping = 0.95; // Dampen control input so you don't` whack out at very slow speeds + + // Maneuvering + maxSteeringAngle = 5; // Max radiens you can rotate the wheel. Smaller number is more maneuverable. + horizontalSurfaceForce = 6; // Horizontal center "wing" (provides "bite" into the wind for climbing/diving and turning) + verticalSurfaceForce = 8; // Vertical center "wing" (controls side slip. lower numbers make MORE slide.) + maneuveringForce = 3000; // Horizontal jets (W,S,D,A key thrust) + steeringForce = 1200; // Steering jets (force applied when you move the mouse) + steeringRollForce = 1600; // Steering jets (how much you heel over when you turn) + rollForce = 18; // Auto-roll (self-correction to right you after you roll/invert) + hoverHeight = 2; // Height off the ground at rest + createHoverHeight = 3; // Height off the ground when created + maxForwardSpeed = 400; // speed in which forward thrust force is no longer applied (meters/second) + + // Turbo Jet + jetForce = 3000; // Afterburner thrust (this is in addition to normal thrust) + minJetEnergy = 1; // Afterburner can't be used if below this threshhold. + jetEnergyDrain = 0; // Energy use of the afterburners (low number is less drain...can be fractional) // Auto stabilize speed + vertThrustMultiple = 3.0; + + // Rigid body + mass = 150; // Mass of the vehicle + bodyFriction = 0; // Don't mess with this. + bodyRestitution = 0.5; // When you hit the ground, how much you rebound. (between 0 and 1) + minRollSpeed = 0; // Don't mess with this. + softImpactSpeed = 14; // Sound hooks. This is the soft hit. + hardImpactSpeed = 25; // Sound hooks. This is the hard hit. + + // Ground Impact Damage (uses DamageType::Ground) + minImpactSpeed = 10; // If hit ground at speed above this then it's an impact. Meters/second + speedDamageScale = 0.06; + + // Object Impact Damage (uses DamageType::Impact) + collDamageThresholdVel = 23.0; + collDamageMultiplier = 0.02; + + // + minTrailSpeed = 15; // The speed your contrail shows up at. + trailEmitter = ContrailEmitter; + forwardJetEmitter = FlyerJetEmitter; + downJetEmitter = FlyerJetEmitter; + + // + jetSound = ScoutFlyerThrustSound; + engineSound = ScoutFlyerEngineSound; + softImpactSound = SoftImpactSound; + hardImpactSound = HardImpactSound; + //wheelImpactSound = WheelImpactSound; + + // + softSplashSoundVelocity = 10.0; + mediumSplashSoundVelocity = 15.0; + hardSplashSoundVelocity = 20.0; + exitSplashSoundVelocity = 10.0; + + exitingWater = VehicleExitWaterMediumSound; + impactWaterEasy = VehicleImpactWaterSoftSound; + impactWaterMedium = VehicleImpactWaterMediumSound; + impactWaterHard = VehicleImpactWaterMediumSound; + waterWakeSound = VehicleWakeMediumSplashSound; + + dustEmitter = VehicleLiftoffDustEmitter; + triggerDustHeight = 4.0; + dustHeight = 1.0; + + damageEmitter[0] = LightDamageSmoke; + damageEmitter[1] = HeavyDamageSmoke; + damageEmitter[2] = DamageBubbles; + damageEmitterOffset[0] = "0.0 -3.0 0.0 "; + damageLevelTolerance[0] = 0.3; + damageLevelTolerance[1] = 0.7; + numDmgEmitterAreas = 1; + + // + max[chaingunAmmo] = 1000; + + minMountDist = 4; + + splashEmitter[0] = VehicleFoamDropletsEmitter; + splashEmitter[1] = VehicleFoamEmitter; + + shieldImpact = VehicleShieldImpact; + + cmdCategory = "Tactical"; + cmdIcon = CMDFlyingScoutIcon; + cmdMiniIconName = "commander/MiniIcons/com_scout_grey"; + targetNameTag = 'Shrike'; + targetTypeTag = 'Turbograv'; + sensorData = AWACPulseSensor; + sensorRadius = AWACPulseSensor.detectRadius; + sensorColor = "255 194 9"; + + checkRadius = 5.5; + observeParameters = "1 10 10"; + + runningLight[0] = ShrikeLight1; +// runningLight[1] = ShrikeLight2; + + shieldEffectScale = "0.937 1.125 0.60"; + +}; + +//************************************************************** +// WEAPONS +//************************************************************** + +datablock ShapeBaseImageData(ScoutChaingunPairImage) +{ + className = WeaponImage; + shapeFile = "weapon_energy_vehicle.dts"; + item = Chaingun; + ammo = ChaingunAmmo; + projectile = ScoutChaingunBullet; + projectileType = TracerProjectile; + mountPoint = 10; +//**original** offset = ".73 0 0"; + offset = "1.93 -0.52 0.044"; + + projectileSpread = 1.0 / 1000.0; + + usesEnergy = true; + useMountEnergy = true; + // DAVEG -- balancing numbers below! + minEnergy = 5; + fireEnergy = 5; + fireTimeout = 125; + + + //-------------------------------------- + stateName[0] = "Activate"; + stateSequence[0] = "Activate"; + stateAllowImageChange[0] = false; + stateTimeoutValue[0] = 0.05; + stateTransitionOnTimeout[0] = "Ready"; + stateTransitionOnNoAmmo[0] = "NoAmmo"; + //-------------------------------------- + stateName[1] = "Ready"; + stateSpinThread[1] = Stop; + stateTransitionOnTriggerDown[1] = "Spinup"; + stateTransitionOnNoAmmo[1] = "NoAmmo"; + //-------------------------------------- + stateName[2] = "NoAmmo"; + stateTransitionOnAmmo[2] = "Ready"; + stateSpinThread[2] = Stop; + stateTransitionOnTriggerDown[2] = "DryFire"; + //-------------------------------------- + stateName[3] = "Spinup"; + stateSpinThread[3] = SpinUp; + stateTimeoutValue[3] = 0.01; + stateWaitForTimeout[3] = false; + stateTransitionOnTimeout[3] = "Fire"; + stateTransitionOnTriggerUp[3] = "Spindown"; + //-------------------------------------- + stateName[4] = "Fire"; + stateSpinThread[4] = FullSpeed; + stateRecoil[4] = LightRecoil; + stateAllowImageChange[4] = false; + stateScript[4] = "onFire"; + stateFire[4] = true; + stateSound[4] = ShrikeBlasterFire; + // IMPORTANT! The stateTimeoutValue below has been replaced by fireTimeOut + // above. + stateTimeoutValue[4] = 0.25; + stateTransitionOnTimeout[4] = "checkState"; + //-------------------------------------- + stateName[5] = "Spindown"; + stateSpinThread[5] = SpinDown; + stateTimeoutValue[5] = 0.01; + stateWaitForTimeout[5] = false; + stateTransitionOnTimeout[5] = "Ready"; + stateTransitionOnTriggerDown[5] = "Spinup"; + //-------------------------------------- + stateName[6] = "EmptySpindown"; +// stateSound[6] = ChaingunSpindownSound; + stateSpinThread[6] = SpinDown; + stateTransitionOnAmmo[6] = "Ready"; + stateTimeoutValue[6] = 0.01; + stateTransitionOnTimeout[6] = "NoAmmo"; + //-------------------------------------- + stateName[7] = "DryFire"; + stateSound[7] = ShrikeBlasterDryFireSound; + stateTransitionOnTriggerUp[7] = "NoAmmo"; + stateTimeoutValue[7] = 0.25; + stateTransitionOnTimeout[7] = "NoAmmo"; + + stateName[8] = "checkState"; + stateTransitionOnTriggerUp[8] = "Spindown"; + stateTransitionOnNoAmmo[8] = "EmptySpindown"; + stateTimeoutValue[8] = 0.01; + stateTransitionOnTimeout[8] = "ready"; +}; + +datablock ShapeBaseImageData(ScoutChaingunImage) : ScoutChaingunPairImage +{ +//**original** offset = "-.73 0 0"; + offset = "-1.93 -0.52 0.044"; + stateScript[3] = "onTriggerDown"; + stateScript[5] = "onTriggerUp"; + stateScript[6] = "onTriggerUp"; +}; + +datablock ShapeBaseImageData(ScoutChaingunParam) +{ + mountPoint = 2; + shapeFile = "turret_muzzlepoint.dts"; + + projectile = ScoutChaingunBullet; + projectileType = TracerProjectile; +}; diff --git a/scripts/vehicles/vehicle_superHavoc.cs b/scripts/vehicles/vehicle_superHavoc.cs new file mode 100644 index 0000000..8fddb15 --- /dev/null +++ b/scripts/vehicles/vehicle_superHavoc.cs @@ -0,0 +1,189 @@ +//************************************************************** +// SUPER HAVOC HEAVY TRANSPORT FLIER +//************************************************************** + +//************************************************************** +// VEHICLE CHARACTERISTICS +//************************************************************** + +datablock FlyingVehicleData(SuperHAPCFlyer) : HavocDamageProfile +{ + spawnOffset = "0 0 6"; + renderWhenDestroyed = false; + + catagory = "Vehicles"; + shapeFile = "vehicle_air_hapc.dts"; + multipassenger = true; + computeCRC = true; + + + debrisShapeName = "vehicle_air_hapc_debris.dts"; + debris = ShapeDebris; + + drag = 0.2; + density = 1.0; + + mountPose[0] = sitting; +// mountPose[1] = sitting; + numMountPoints = 6; + isProtectedMountPoint[0] = true; + isProtectedMountPoint[1] = true; + isProtectedMountPoint[2] = true; + isProtectedMountPoint[3] = true; + isProtectedMountPoint[4] = true; + isProtectedMountPoint[5] = true; + canControl = true; + cameraMaxDist = 17; + cameraOffset = 2; + cameraLag = 8.5; + explosion = LargeAirVehicleExplosion; + explosionDamage = 0.5; + explosionRadius = 5.0; + + maxDamage = 3.50; + destroyedLevel = 3.50; + + isShielded = true; + rechargeRate = 0.8; + energyPerDamagePoint = 200; + maxEnergy = 550; + minDrag = 100; // Linear Drag + rotationalDrag = 2700; // Anguler Drag + + // Auto stabilize speed + maxAutoSpeed = 20; + autoAngularForce = 3000; // Angular stabilizer force + autoLinearForce = 450; // Linear stabilzer force + autoInputDamping = 0.95; // + + // Maneuvering + maxSteeringAngle = 4; + horizontalSurfaceForce = 10; // Horizontal center "wing" + verticalSurfaceForce = 10; // Vertical center "wing" + maneuveringForce = 12000; // Horizontal jets + steeringForce = 3000; // Steering jets + steeringRollForce = 600; // Steering jets + rollForce = 12; // Auto-roll + hoverHeight = 3; // Height off the ground at rest + createHoverHeight = 6; // Height off the ground when created + maxForwardSpeed = 1000; // speed in which forward thrust force is no longer applied (meters/second) + + // Turbo Jet + jetForce = 24000; + minJetEnergy = 55; + jetEnergyDrain = 0.1; + vertThrustMultiple = 4.0; + + + dustEmitter = LargeVehicleLiftoffDustEmitter; + triggerDustHeight = 4.0; + dustHeight = 2.0; + + damageEmitter[0] = LightDamageSmoke; + damageEmitter[1] = HeavyDamageSmoke; + damageEmitter[2] = DamageBubbles; + damageEmitterOffset[0] = "3.0 -3.0 0.0 "; + damageEmitterOffset[1] = "-3.0 -3.0 0.0 "; + damageLevelTolerance[0] = 0.3; + damageLevelTolerance[1] = 0.7; + numDmgEmitterAreas = 2; + + // Rigid body + mass = 550; + bodyFriction = 0; + bodyRestitution = 0.3; + minRollSpeed = 0; + softImpactSpeed = 12; // Sound hooks. This is the soft hit. + hardImpactSpeed = 15; // Sound hooks. This is the hard hit. + + // Ground Impact Damage (uses DamageType::Ground) + minImpactSpeed = 125; // If hit ground at speed above this then it's an impact. Meters/second + speedDamageScale = 0.060; + + // Object Impact Damage (uses DamageType::Impact) + collDamageThresholdVel = 128; + collDamageMultiplier = 0.020; + + // + minTrailSpeed = 0.1; + trailEmitter = ContrailEmitter; + forwardJetEmitter = FlyerJetEmitter; + downJetEmitter = FlyerJetEmitter; + + // + jetSound = HAPCFlyerThrustSound; + engineSound = HAPCFlyerEngineSound; + softImpactSound = SoftImpactSound; + hardImpactSound = HardImpactSound; + //wheelImpactSound = WheelImpactSound; + + // + softSplashSoundVelocity = 5.0; + mediumSplashSoundVelocity = 8.0; + hardSplashSoundVelocity = 12.0; + exitSplashSoundVelocity = 8.0; + + exitingWater = VehicleExitWaterHardSound; + impactWaterEasy = VehicleImpactWaterSoftSound; + impactWaterMedium = VehicleImpactWaterMediumSound; + impactWaterHard = VehicleImpactWaterHardSound; + waterWakeSound = VehicleWakeHardSplashSound; + + minMountDist = 4; + + splashEmitter[0] = VehicleFoamDropletsEmitter; + splashEmitter[1] = VehicleFoamEmitter; + + shieldImpact = VehicleShieldImpact; + + cmdCategory = "Tactical"; + cmdIcon = CMDFlyingHAPCIcon; + cmdMiniIconName = "commander/MiniIcons/com_hapc_grey"; + targetNameTag = 'Super Havoc'; + targetTypeTag = 'Heavy Transport'; + sensorData = VehiclePulseSensor; + + checkRadius = 7.8115; + observeParameters = "1 15 15"; + + stuckTimerTicks = 32; // If the hapc spends more than 1 sec in contact with something + stuckTimerAngle = 80; // with a > 80 deg. pitch, BOOM! + + shieldEffectScale = "1.0 0.9375 0.45"; +}; + +function SuperHAPCFlyer::hasDismountOverrides(%data, %obj) +{ + return true; +} + +function SuperHAPCFlyer::getDismountOverride(%data, %obj, %mounted) +{ + %node = -1; + for (%i = 0; %i < %data.numMountPoints; %i++) + { + if (%obj.getMountNodeObject(%i) == %mounted) + { + %node = %i; + break; + } + } + if (%node == -1) + { + warning("Couldn't find object mount point"); + return "0 0 1"; + } + + if (%node == 3 || %node == 2) + { + return "-1 0 1"; + } + else if (%node == 5 || %node == 4) + { + return "1 0 1"; + } + else + { + return "0 0 1"; + } +} diff --git a/scripts/vehicles/vehicle_superWildcat.cs b/scripts/vehicles/vehicle_superWildcat.cs new file mode 100644 index 0000000..73e190b --- /dev/null +++ b/scripts/vehicles/vehicle_superWildcat.cs @@ -0,0 +1,146 @@ +//************************************************************** +// SUPER WILDCAT GRAV CYCLE +//************************************************************** + +//************************************************************** +// VEHICLE CHARACTERISTICS +//************************************************************** + +datablock HoverVehicleData(SuperScoutVehicle) : WildcatDamageProfile +{ + spawnOffset = "0 0 1"; + canControl = true; + floatingGravMag = 3.5; + + catagory = "Vehicles"; + shapeFile = "vehicle_grav_scout.dts"; + computeCRC = true; + + debrisShapeName = "vehicle_grav_scout_debris.dts"; + debris = ShapeDebris; + renderWhenDestroyed = false; + + drag = 0.0; + density = 0.9; + + mountPose[0] = scoutRoot; + cameraMaxDist = 5.0; + cameraOffset = 0.7; + cameraLag = 0.5; + numMountPoints = 1; + isProtectedMountPoint[0] = true; + explosion = VehicleExplosion; + explosionDamage = 0.5; + explosionRadius = 5.0; + + lightOnly = 1; + + maxDamage = 1.60; + destroyedLevel = 1.60; + + isShielded = true; + rechargeRate = 0.9; + energyPerDamagePoint = 1; + maxEnergy = 450; + minJetEnergy = 1; + jetEnergyDrain = 0.1; + + // Rigid Body + mass = 400; + bodyFriction = 0.1; + bodyRestitution = 0.5; + softImpactSpeed = 120; // Play SoftImpact Sound + hardImpactSpeed = 128; // Play HardImpact Sound + + // Ground Impact Damage (uses DamageType::Ground) + minImpactSpeed = 129; + speedDamageScale = 0.010; + + // Object Impact Damage (uses DamageType::Impact) + collDamageThresholdVel = 123; + collDamageMultiplier = 0.030; + + dragForce = 45 / 45.0; + vertFactor = 0.0; + floatingThrustFactor = 0.35; + + mainThrustForce = 90; + reverseThrustForce = 90; + strafeThrustForce = 90; + turboFactor = 3.5; + + brakingForce = 90; + brakingActivationSpeed = 4; + + stabLenMin = 2.25; + stabLenMax = 3.75; + stabSpringConstant = 30; + stabDampingConstant = 16; + + gyroDrag = 16; + normalForce = 30; + restorativeForce = 20; + steeringForce = 30; + rollForce = 15; + pitchForce = 7; + + dustEmitter = VehicleLiftoffDustEmitter; + triggerDustHeight = 2.5; + dustHeight = 1.0; + dustTrailEmitter = TireEmitter; + dustTrailOffset = "0.0 -1.0 0.5"; + triggerTrailHeight = 30.6; + dustTrailFreqMod = 15.0; + + jetSound = ScoutSqueelSound; + engineSound = ScoutEngineSound; + floatSound = ScoutThrustSound; + softImpactSound = GravSoftImpactSound; + hardImpactSound = HardImpactSound; + //wheelImpactSound = WheelImpactSound; + + // + softSplashSoundVelocity = 10.0; + mediumSplashSoundVelocity = 20.0; + hardSplashSoundVelocity = 30.0; + exitSplashSoundVelocity = 10.0; + + exitingWater = VehicleExitWaterSoftSound; + impactWaterEasy = VehicleImpactWaterSoftSound; + impactWaterMedium = VehicleImpactWaterSoftSound; + impactWaterHard = VehicleImpactWaterMediumSound; + waterWakeSound = VehicleWakeSoftSplashSound; + + minMountDist = 4; + + damageEmitter[0] = SmallLightDamageSmoke; + damageEmitter[1] = SmallHeavyDamageSmoke; + damageEmitter[2] = DamageBubbles; + damageEmitterOffset[0] = "0.0 -1.5 0.5 "; + damageLevelTolerance[0] = 0.3; + damageLevelTolerance[1] = 0.7; + numDmgEmitterAreas = 1; + + splashEmitter[0] = VehicleFoamDropletsEmitter; + splashEmitter[1] = VehicleFoamEmitter; + + shieldImpact = VehicleShieldImpact; + + forwardJetEmitter = WildcatJetEmitter; + + cmdCategory = Tactical; + cmdIcon = CMDHoverScoutIcon; + cmdMiniIconName = "commander/MiniIcons/com_landscout_grey"; + targetNameTag = 'Super WildCat'; + targetTypeTag = 'Grav Cycle'; + sensorData = VehiclePulseSensor; + + checkRadius = 1.7785; + observeParameters = "1 10 10"; + + runningLight[0] = WildcatLight1; + runningLight[1] = WildcatLight2; + runningLight[2] = WildcatLight3; + + shieldEffectScale = "0.9375 1.125 0.6"; +}; diff --git a/scripts/vehicles/vehicle_tank.cs b/scripts/vehicles/vehicle_tank.cs new file mode 100644 index 0000000..1488dd4 --- /dev/null +++ b/scripts/vehicles/vehicle_tank.cs @@ -0,0 +1,686 @@ +//************************************************************** +// BEOWULF ASSAULT VEHICLE +//************************************************************** +//************************************************************** +// SOUNDS +//************************************************************** +datablock EffectProfile(AssaultVehicleEngineEffect) +{ + effectname = "vehicles/tank_engine"; + minDistance = 5.0; + maxDistance = 10.0; +}; + +datablock EffectProfile(AssaultVehicleThrustEffect) +{ + effectname = "vehicles/tank_boost"; + minDistance = 5.0; + maxDistance = 10.0; +}; + +datablock EffectProfile(AssaultTurretActivateEffect) +{ + effectname = "vehicles/tank_activate"; + minDistance = 5.0; + maxDistance = 10.0; +}; + +datablock EffectProfile(AssaultMortarDryFireEffect) +{ + effectname = "weapons/mortar_dryfire"; + minDistance = 5.0; + maxDistance = 10.0; +}; + +datablock EffectProfile(AssaultMortarFireEffect) +{ + effectname = "vehicles/tank_mortar_fire"; + minDistance = 5.0; + maxDistance = 10.0; +}; + +datablock EffectProfile(AssaultMortarReloadEffect) +{ + effectname = "weapons/mortar_reload"; + minDistance = 5.0; + maxDistance = 10.0; +}; + +datablock EffectProfile(AssaultChaingunFireEffect) +{ + effectname = "weapons/chaingun_fire"; + minDistance = 5.0; + maxDistance = 10.0; +}; + +datablock AudioProfile(AssaultVehicleSkid) +{ + filename = "fx/vehicles/tank_skid.wav"; + description = ClosestLooping3d; + preload = true; +}; + +datablock AudioProfile(AssaultVehicleEngineSound) +{ + filename = "fx/vehicles/tank_engine.wav"; + description = AudioDefaultLooping3d; + preload = true; + effect = AssaultVehicleEngineEffect; +}; + +datablock AudioProfile(AssaultVehicleThrustSound) +{ + filename = "fx/vehicles/tank_boost.wav"; + description = AudioDefaultLooping3d; + preload = true; + effect = AssaultVehicleThrustEffect; +}; + +datablock AudioProfile(AssaultChaingunFireSound) +{ + filename = "fx/vehicles/tank_chaingun.wav"; + description = AudioDefaultLooping3d; + preload = true; + effect = AssaultChaingunFireEffect; +}; + +datablock AudioProfile(AssaultChaingunReloadSound) +{ + filename = "fx/weapons/chaingun_dryfire.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(TankChaingunProjectile) +{ + filename = "fx/weapons/chaingun_projectile.wav"; + description = ProjectileLooping3d; + preload = true; +}; + +datablock AudioProfile(AssaultTurretActivateSound) +{ + filename = "fx/vehicles/tank_activate.wav"; + description = AudioClose3d; + preload = true; + effect = AssaultTurretActivateEffect; +}; + +datablock AudioProfile(AssaultChaingunDryFireSound) +{ + filename = "fx/weapons/chaingun_dryfire.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(AssaultChaingunIdleSound) +{ + filename = "fx/misc/diagnostic_on.wav"; + description = ClosestLooping3d; + preload = true; +}; + +datablock AudioProfile(AssaultMortarDryFireSound) +{ + filename = "fx/weapons/mortar_dryfire.wav"; + description = AudioClose3d; + preload = true; + effect = AssaultMortarDryFireEffect; +}; + +datablock AudioProfile(AssaultMortarFireSound) +{ + filename = "fx/vehicles/tank_mortar_fire.wav"; + description = AudioClose3d; + preload = true; + effect = AssaultMortarFireEffect; +}; + +datablock AudioProfile(AssaultMortarReloadSound) +{ + filename = "fx/weapons/mortar_reload.wav"; + description = AudioClose3d; + preload = true; + effect = AssaultMortarReloadEffect; +}; + +datablock AudioProfile(AssaultMortarIdleSound) +{ + filename = "fx/misc/diagnostic_on.wav"; + description = ClosestLooping3d; + preload = true; +}; + +//************************************************************** +// LIGHTS +//************************************************************** +datablock RunningLightData(TankLight1) +{ + radius = 1.5; + color = "1.0 1.0 1.0 0.2"; + nodeName = "Headlight_node01"; + direction = "0.0 1.0 0.0"; + texture = "special/headlight4"; +}; + +datablock RunningLightData(TankLight2) +{ + radius = 1.5; + color = "1.0 1.0 1.0 0.2"; + nodeName = "Headlight_node02"; + direction = "0.0 1.0 0.0"; + texture = "special/headlight4"; +}; + +datablock RunningLightData(TankLight3) +{ + radius = 1.5; + color = "1.0 1.0 1.0 0.2"; + nodeName = "Headlight_node03"; + direction = "0.0 1.0 0.0"; + texture = "special/headlight4"; +}; + +datablock RunningLightData(TankLight4) +{ + radius = 1.5; + color = "1.0 1.0 1.0 0.2"; + nodeName = "Headlight_node04"; + direction = "0.0 1.0 0.0"; + texture = "special/headlight4"; +}; + +//************************************************************** +// VEHICLE CHARACTERISTICS +//************************************************************** + +datablock HoverVehicleData(AssaultVehicle) : TankDamageProfile +{ + spawnOffset = "0 0 4"; + canControl = true; + floatingGravMag = 4.5; + + catagory = "Vehicles"; + shapeFile = "vehicle_grav_tank.dts"; + multipassenger = true; + computeCRC = true; + renderWhenDestroyed = false; + + weaponNode = 1; + + debrisShapeName = "vehicle_land_assault_debris.dts"; + debris = ShapeDebris; + + drag = 0.0; + density = 0.9; + + mountPose[0] = sitting; + mountPose[1] = sitting; + numMountPoints = 2; + isProtectedMountPoint[0] = true; + isProtectedMountPoint[1] = true; + + cameraMaxDist = 20; + cameraOffset = 3; + cameraLag = 1.5; + explosion = LargeGroundVehicleExplosion; + explosionDamage = 0.5; + explosionRadius = 5.0; + + maxSteeringAngle = 0.5; // 20 deg. + + maxDamage = 3.15; + destroyedLevel = 3.15; + + isShielded = true; + rechargeRate = 1.0; + energyPerDamagePoint = 135; + maxEnergy = 400; + minJetEnergy = 15; + jetEnergyDrain = 2.0; + + // Rigid Body + mass = 1500; + bodyFriction = 0.8; + bodyRestitution = 0.5; + minRollSpeed = 3; + gyroForce = 400; + gyroDamping = 0.3; + stabilizerForce = 20; + minDrag = 10; + softImpactSpeed = 15; // Play SoftImpact Sound + hardImpactSpeed = 18; // Play HardImpact Sound + + // Ground Impact Damage (uses DamageType::Ground) + minImpactSpeed = 17; + speedDamageScale = 0.060; + + // Object Impact Damage (uses DamageType::Impact) + collDamageThresholdVel = 18; + collDamageMultiplier = 0.045; + + dragForce = 40 / 20; + vertFactor = 0.0; + floatingThrustFactor = 0.15; + + mainThrustForce = 50; + reverseThrustForce = 40; + strafeThrustForce = 40; + turboFactor = 1.7; + + brakingForce = 25; + brakingActivationSpeed = 4; + + stabLenMin = 3.25; + stabLenMax = 4; + stabSpringConstant = 50; + stabDampingConstant = 20; + + gyroDrag = 20; + normalForce = 20; + restorativeForce = 10; + steeringForce = 15; + rollForce = 5; + pitchForce = 3; + + dustEmitter = TankDustEmitter; + triggerDustHeight = 3.5; + dustHeight = 1.0; + dustTrailEmitter = TireEmitter; + dustTrailOffset = "0.0 -1.0 0.5"; + triggerTrailHeight = 3.6; + dustTrailFreqMod = 15.0; + + jetSound = AssaultVehicleThrustSound; + engineSound = AssaultVehicleEngineSound; + floatSound = AssaultVehicleSkid; + softImpactSound = GravSoftImpactSound; + hardImpactSound = HardImpactSound; + wheelImpactSound = WheelImpactSound; + + forwardJetEmitter = TankJetEmitter; + + // + softSplashSoundVelocity = 5.0; + mediumSplashSoundVelocity = 10.0; + hardSplashSoundVelocity = 15.0; + exitSplashSoundVelocity = 10.0; + + exitingWater = VehicleExitWaterMediumSound; + impactWaterEasy = VehicleImpactWaterSoftSound; + impactWaterMedium = VehicleImpactWaterMediumSound; + impactWaterHard = VehicleImpactWaterMediumSound; + waterWakeSound = VehicleWakeMediumSplashSound; + + minMountDist = 4; + + damageEmitter[0] = SmallLightDamageSmoke; + damageEmitter[1] = SmallHeavyDamageSmoke; + damageEmitter[2] = DamageBubbles; + damageEmitterOffset[0] = "0.0 -1.5 3.5 "; + damageLevelTolerance[0] = 0.3; + damageLevelTolerance[1] = 0.7; + numDmgEmitterAreas = 1; + + splashEmitter[0] = VehicleFoamDropletsEmitter; + splashEmitter[1] = VehicleFoamEmitter; + + shieldImpact = VehicleShieldImpact; + + cmdCategory = "Tactical"; + cmdIcon = CMDGroundTankIcon; + cmdMiniIconName = "commander/MiniIcons/com_tank_grey"; + targetNameTag = 'Beowulf'; + targetTypeTag = 'Assault Tank'; + sensorData = VehiclePulseSensor; + + checkRadius = 5.5535; + observeParameters = "1 10 10"; + runningLight[0] = TankLight1; + runningLight[1] = TankLight2; + runningLight[2] = TankLight3; + runningLight[3] = TankLight4; + shieldEffectScale = "0.9 1.0 0.6"; + showPilotInfo = 1; +}; + +//************************************************************** +// WEAPONS +//************************************************************** + +//------------------------------------- +// ASSAULT CHAINGUN (projectile) +//------------------------------------- + +datablock TracerProjectileData(AssaultChaingunBullet) +{ + doDynamicClientHits = true; + + projectileShapeName = ""; + directDamage = 0.16; + directDamageType = $DamageType::TankChaingun; + hasDamageRadius = false; + splash = ChaingunSplash; + + kickbackstrength = 0.0; + sound = TankChaingunProjectile; + + dryVelocity = 425.0; + wetVelocity = 100.0; + velInheritFactor = 1.0; + fizzleTimeMS = 3000; + lifetimeMS = 3000; + explodeOnDeath = false; + reflectOnWaterImpactAngle = 0.0; + explodeOnWaterImpact = false; + deflectionOnWaterImpact = 0.0; + fizzleUnderwaterMS = 3000; + + tracerLength = 15.0; + tracerAlpha = false; + tracerMinPixels = 6; + tracerColor = 211.0/255.0 @ " " @ 215.0/255.0 @ " " @ 120.0/255.0 @ " 0.75"; + tracerTex[0] = "special/tracer00"; + tracerTex[1] = "special/tracercross"; + tracerWidth = 0.10; + crossSize = 0.20; + crossViewAng = 0.990; + renderCross = true; + + decalData[0] = ChaingunDecal1; + decalData[1] = ChaingunDecal2; + decalData[2] = ChaingunDecal3; + decalData[3] = ChaingunDecal4; + decalData[4] = ChaingunDecal5; + decalData[5] = ChaingunDecal6; + + activateDelayMS = 100; + + explosion = ChaingunExplosion; +}; + +//------------------------------------- +// ASSAULT CHAINGUN CHARACTERISTICS +//------------------------------------- + +datablock TurretData(AssaultPlasmaTurret) : TurretDamageProfile +{ + className = VehicleTurret; + catagory = "Turrets"; + shapeFile = "Turret_tank_base.dts"; + preload = true; + canControl = true; + cmdCategory = "Tactical"; + cmdIcon = CMDGroundTankIcon; + cmdMiniIconName = "commander/MiniIcons/com_tank_grey"; + targetNameTag = 'Beowulf'; + targetTypeTag = 'Assault Tank turret'; + mass = 1.0; // Not really relevant + + maxEnergy = 1; + maxDamage = AssaultVehicle.maxDamage; + destroyedLevel = AssaultVehicle.destroyedLevel; + repairRate = 0; + + // capacitor + maxCapacitorEnergy = 250; + capacitorRechargeRate = 1.0; + + thetaMin = 0; + thetaMax = 100; + + inheritEnergyFromMount = true; + firstPersonOnly = true; + useEyePoint = true; + numWeapons = 2; + + cameraDefaultFov = 90.0; + cameraMinFov = 5.0; + cameraMaxFov = 120.0; + + targetNameTag = 'Beowulf Chaingun'; + targetTypeTag = 'Turret'; +}; + +datablock TurretImageData(AssaultPlasmaTurretBarrel) +{ + shapeFile = "turret_tank_barrelchain.dts"; + mountPoint = 1; + + projectile = AssaultChaingunBullet; + projectileType = TracerProjectile; + + casing = ShellDebris; + shellExitDir = "1.0 0.3 1.0"; + shellExitOffset = "0.15 -0.56 -0.1"; + shellExitVariance = 15.0; + shellVelocity = 3.0; + + projectileSpread = 12.0 / 1000.0; + + useCapacitor = true; + usesEnergy = true; + useMountEnergy = true; + fireEnergy = 7.5; + minEnergy = 15.0; + + // Turret parameters + activationMS = 4000; + deactivateDelayMS = 500; + thinkTimeMS = 200; + degPerSecTheta = 360; + degPerSecPhi = 360; + attackRadius = 75; + + // State transitions + stateName[0] = "Activate"; + stateTransitionOnNotLoaded[0] = "Dead"; + stateTransitionOnLoaded[0] = "ActivateReady"; + stateSound[0] = AssaultTurretActivateSound; + + stateName[1] = "ActivateReady"; + stateSequence[1] = "Activate"; + stateSound[1] = AssaultTurretActivateSound; + stateTimeoutValue[1] = 1; + stateTransitionOnTimeout[1] = "Ready"; + stateTransitionOnNotLoaded[1] = "Deactivate"; + + stateName[2] = "Ready"; + stateTransitionOnNotLoaded[2] = "Deactivate"; + stateTransitionOnTriggerDown[2] = "Fire"; + stateTransitionOnNoAmmo[2] = "NoAmmo"; + + stateName[3] = "Fire"; + stateSequence[3] = "Fire"; + stateSequenceRandomFlash[3] = true; + stateFire[3] = true; + stateAllowImageChange[3] = false; + stateSound[3] = AssaultChaingunFireSound; + stateScript[3] = "onFire"; + stateTimeoutValue[3] = 0.1; + stateTransitionOnTimeout[3] = "Fire"; + stateTransitionOnTriggerUp[3] = "Reload"; + stateTransitionOnNoAmmo[3] = "noAmmo"; + + stateName[4] = "Reload"; + stateSequence[4] = "Reload"; + stateTimeoutValue[4] = 0.1; + stateAllowImageChange[4] = false; + stateTransitionOnTimeout[4] = "Ready"; + stateTransitionOnNoAmmo[4] = "NoAmmo"; + stateWaitForTimeout[4] = true; + + stateName[5] = "Deactivate"; + stateSequence[5] = "Activate"; + stateDirection[5] = false; + stateTimeoutValue[5] = 30; + stateTransitionOnTimeout[5] = "ActivateReady"; + + stateName[6] = "Dead"; + stateTransitionOnLoaded[6] = "ActivateReady"; + stateTransitionOnTriggerDown[6] = "DryFire"; + + stateName[7] = "DryFire"; + stateSound[7] = AssaultChaingunDryFireSound; + stateTimeoutValue[7] = 0.5; + stateTransitionOnTimeout[7] = "NoAmmo"; + + stateName[8] = "NoAmmo"; + stateTransitionOnAmmo[8] = "Reload"; + stateSequence[8] = "NoAmmo"; + stateTransitionOnTriggerDown[8] = "DryFire"; + +}; + +//------------------------------------- +// ASSAULT MORTAR (projectile) +//------------------------------------- + +datablock ItemData(AssaultMortarAmmo) +{ + className = Ammo; + catagory = "Ammo"; + shapeFile = "repair_kit.dts"; + mass = 1; + elasticity = 0.5; + friction = 0.6; + pickupRadius = 1; + + computeCRC = true; +}; + +datablock GrenadeProjectileData(AssaultMortar) +{ + projectileShapeName = "mortar_projectile.dts"; + emitterDelay = -1; + directDamage = 0.0; + hasDamageRadius = true; + indirectDamage = 1.0; + damageRadius = 25.0; + radiusDamageType = $DamageType::TankMortar; + kickBackStrength = 2500; + + sound = MortarProjectileSound; + explosion = "MortarExplosion"; + velInheritFactor = 1.0; + + baseEmitter = MortarSmokeEmitter; + + grenadeElasticity = 0.0; + grenadeFriction = 0.4; + armingDelayMS = 250; + muzzleVelocity = 65; + drag = 0.1; + + hasLight = true; + lightRadius = 4; + lightColor = "0.1 0.4 0.1"; +}; + +//------------------------------------- +// ASSAULT MORTAR CHARACTERISTICS +//------------------------------------- + +datablock TurretImageData(AssaultMortarTurretBarrel) +{ + shapeFile = "turret_tank_barrelmortar.dts"; + mountPoint = 0; + +// ammo = AssaultMortarAmmo; + projectile = AssaultMortar; + projectileType = GrenadeProjectile; + + usesEnergy = true; + useMountEnergy = true; + fireEnergy = 77.00; + minEnergy = 77.00; + useCapacitor = true; + + // Turret parameters + activationMS = 4000; + deactivateDelayMS = 1500; + thinkTimeMS = 200; + degPerSecTheta = 360; + degPerSecPhi = 360; + attackRadius = 75; + + // State transitions + stateName[0] = "Activate"; + stateTransitionOnNotLoaded[0] = "Dead"; + stateTransitionOnLoaded[0] = "ActivateReady"; + + stateName[1] = "ActivateReady"; + stateSequence[1] = "Activate"; + stateSound[1] = AssaultTurretActivateSound; + stateTimeoutValue[1] = 1.0; + stateTransitionOnTimeout[1] = "Ready"; + stateTransitionOnNotLoaded[1] = "Deactivate"; + + stateName[2] = "Ready"; + stateTransitionOnNotLoaded[2] = "Deactivate"; + stateTransitionOnNoAmmo[2] = "NoAmmo"; + stateTransitionOnTriggerDown[2] = "Fire"; + + stateName[3] = "Fire"; + stateSequence[3] = "Fire"; + stateTransitionOnTimeout[3] = "Reload"; + stateTimeoutValue[3] = 1.0; + stateFire[3] = true; + stateRecoil[3] = LightRecoil; + stateAllowImageChange[3] = false; + stateSound[3] = AssaultMortarFireSound; + stateScript[3] = "onFire"; + + stateName[4] = "Reload"; + stateSequence[4] = "Reload"; + stateTimeoutValue[4] = 1.0; + stateAllowImageChange[4] = false; + stateTransitionOnTimeout[4] = "Ready"; + //stateTransitionOnNoAmmo[4] = "NoAmmo"; + stateWaitForTimeout[4] = true; + + stateName[5] = "Deactivate"; + stateDirection[5] = false; + stateSequence[5] = "Activate"; + stateTimeoutValue[5] = 1.0; + stateTransitionOnLoaded[5] = "ActivateReady"; + stateTransitionOnTimeout[5] = "Dead"; + + stateName[6] = "Dead"; + stateTransitionOnLoaded[6] = "ActivateReady"; + stateTransitionOnTriggerDown[6] = "DryFire"; + + stateName[7] = "DryFire"; + stateSound[7] = AssaultMortarDryFireSound; + stateTimeoutValue[7] = 1.0; + stateTransitionOnTimeout[7] = "NoAmmo"; + + stateName[8] = "NoAmmo"; + stateSequence[8] = "NoAmmo"; + stateTransitionOnAmmo[8] = "Reload"; + stateTransitionOnTriggerDown[8] = "DryFire"; +}; + +datablock TurretImageData(AssaultTurretParam) +{ + mountPoint = 2; + shapeFile = "turret_muzzlepoint.dts"; + + projectile = AssaultChaingunBullet; + projectileType = TracerProjectile; + + useCapacitor = true; + usesEnergy = true; + + // Turret parameters + activationMS = 1000; + deactivateDelayMS = 1500; + thinkTimeMS = 200; + degPerSecTheta = 500; + degPerSecPhi = 500; + + attackRadius = 75; +}; + + + diff --git a/scripts/vehicles/vehicle_wildcat.cs b/scripts/vehicles/vehicle_wildcat.cs new file mode 100644 index 0000000..e7a635b --- /dev/null +++ b/scripts/vehicles/vehicle_wildcat.cs @@ -0,0 +1,222 @@ +//************************************************************** +// WILDCAT GRAV CYCLE +//************************************************************** +//************************************************************** +// SOUNDS +//************************************************************** +datablock EffectProfile(ScoutEngineEffect) +{ + effectname = "vehicles/outrider_engine"; + minDistance = 5.0; + maxDistance = 10.0; +}; + +datablock EffectProfile(ScoutThrustEffect) +{ + effectname = "vehicles/outrider_boost"; + minDistance = 5.0; + maxDistance = 10.0; +}; + +datablock AudioProfile(ScoutSqueelSound) +{ + filename = "fx/vehicles/outrider_skid.wav"; + description = ClosestLooping3d; + preload = true; +}; + +// Scout +datablock AudioProfile(ScoutEngineSound) +{ + filename = "fx/vehicles/outrider_engine.wav"; + description = AudioDefaultLooping3d; + preload = true; + effect = ScoutEngineEffect; +}; + +datablock AudioProfile(ScoutThrustSound) +{ + filename = "fx/vehicles/outrider_boost.wav"; + description = AudioDefaultLooping3d; + preload = true; + effect = ScoutThrustEffect; +}; + +//************************************************************** +// LIGHTS +//************************************************************** +datablock RunningLightData(WildcatLight1) +{ + radius = 1.0; + color = "1.0 1.0 1.0 0.3"; + nodeName = "Headlight_node01"; + direction = "-1.0 1.0 0.0"; + texture = "special/headlight4"; +}; + +datablock RunningLightData(WildcatLight2) +{ + radius = 1.0; + color = "1.0 1.0 1.0 0.3"; + nodeName = "Headlight_node02"; + direction = "1.0 1.0 0.0"; + texture = "special/headlight4"; +}; + +datablock RunningLightData(WildcatLight3) +{ + type = 2; + radius = 100.0; + color = "1.0 1.0 1.0 1.0"; + offset = "0.0 0.0 0.0"; + direction = "0.0 1.0 0.0"; + texture = "special/projheadlight"; +}; + +//************************************************************** +// VEHICLE CHARACTERISTICS +//************************************************************** + +datablock HoverVehicleData(ScoutVehicle) : WildcatDamageProfile +{ + spawnOffset = "0 0 1"; + canControl = true; + floatingGravMag = 3.5; + + catagory = "Vehicles"; + shapeFile = "vehicle_grav_scout.dts"; + computeCRC = true; + + debrisShapeName = "vehicle_grav_scout_debris.dts"; + debris = ShapeDebris; + renderWhenDestroyed = false; + + drag = 0.0; + density = 0.9; + + mountPose[0] = scoutRoot; + cameraMaxDist = 5.0; + cameraOffset = 0.7; + cameraLag = 0.5; + numMountPoints = 1; + isProtectedMountPoint[0] = true; + explosion = VehicleExplosion; + explosionDamage = 0.5; + explosionRadius = 5.0; + + lightOnly = 1; + + maxDamage = 0.60; + destroyedLevel = 0.60; + + isShielded = true; + rechargeRate = 0.7; + energyPerDamagePoint = 75; + maxEnergy = 150; + minJetEnergy = 15; + jetEnergyDrain = 1.3; + + // Rigid Body + mass = 400; + bodyFriction = 0.1; + bodyRestitution = 0.5; + softImpactSpeed = 20; // Play SoftImpact Sound + hardImpactSpeed = 28; // Play HardImpact Sound + + // Ground Impact Damage (uses DamageType::Ground) + minImpactSpeed = 29; + speedDamageScale = 0.010; + + // Object Impact Damage (uses DamageType::Impact) + collDamageThresholdVel = 23; + collDamageMultiplier = 0.030; + + dragForce = 25 / 45.0; + vertFactor = 0.0; + floatingThrustFactor = 0.35; + + mainThrustForce = 30; + reverseThrustForce = 10; + strafeThrustForce = 8; + turboFactor = 1.5; + + brakingForce = 25; + brakingActivationSpeed = 4; + + stabLenMin = 2.25; + stabLenMax = 3.75; + stabSpringConstant = 30; + stabDampingConstant = 16; + + gyroDrag = 16; + normalForce = 30; + restorativeForce = 20; + steeringForce = 30; + rollForce = 15; + pitchForce = 7; + + dustEmitter = VehicleLiftoffDustEmitter; + triggerDustHeight = 2.5; + dustHeight = 1.0; + dustTrailEmitter = TireEmitter; + dustTrailOffset = "0.0 -1.0 0.5"; + triggerTrailHeight = 3.6; + dustTrailFreqMod = 15.0; + + jetSound = ScoutSqueelSound; + engineSound = ScoutEngineSound; + floatSound = ScoutThrustSound; + softImpactSound = GravSoftImpactSound; + hardImpactSound = HardImpactSound; + //wheelImpactSound = WheelImpactSound; + + // + softSplashSoundVelocity = 10.0; + mediumSplashSoundVelocity = 20.0; + hardSplashSoundVelocity = 30.0; + exitSplashSoundVelocity = 10.0; + + exitingWater = VehicleExitWaterSoftSound; + impactWaterEasy = VehicleImpactWaterSoftSound; + impactWaterMedium = VehicleImpactWaterSoftSound; + impactWaterHard = VehicleImpactWaterMediumSound; + waterWakeSound = VehicleWakeSoftSplashSound; + + minMountDist = 4; + + damageEmitter[0] = SmallLightDamageSmoke; + damageEmitter[1] = SmallHeavyDamageSmoke; + damageEmitter[2] = DamageBubbles; + damageEmitterOffset[0] = "0.0 -1.5 0.5 "; + damageLevelTolerance[0] = 0.3; + damageLevelTolerance[1] = 0.7; + numDmgEmitterAreas = 1; + + splashEmitter[0] = VehicleFoamDropletsEmitter; + splashEmitter[1] = VehicleFoamEmitter; + + shieldImpact = VehicleShieldImpact; + + forwardJetEmitter = WildcatJetEmitter; + + cmdCategory = Tactical; + cmdIcon = CMDHoverScoutIcon; + cmdMiniIconName = "commander/MiniIcons/com_landscout_grey"; + targetNameTag = 'WildCat'; + targetTypeTag = 'Grav Cycle'; + sensorData = VehiclePulseSensor; + + checkRadius = 1.7785; + observeParameters = "1 10 10"; + + runningLight[0] = WildcatLight1; + runningLight[1] = WildcatLight2; + runningLight[2] = WildcatLight3; + + shieldEffectScale = "0.9375 1.125 0.6"; +}; + +//************************************************************** +// WEAPONS +//************************************************************** + diff --git a/scripts/weapTurretCode.cs b/scripts/weapTurretCode.cs new file mode 100644 index 0000000..eabe4c1 --- /dev/null +++ b/scripts/weapTurretCode.cs @@ -0,0 +1,927 @@ +//-------------------------------------- Ammo functions +function Ammo::onCollision(%data, %obj, %col) +{ + // %data = datablock of object; %obj = object number + // %col = thing that collided with object (hopefully a player) + + if (%col.getDataBlock().className $= Armor) + { + %ammoName = %data.getName(); + %ammoStore = %col.inv[%ammoName]; + + // if player has ammo pack, increase max amount of ammo + if(%col.getMountedImage($BackpackSlot) != 0) + { + if(%col.getMountedImage($BackpackSlot).getName() $= "AmmoPackImage") + %aMax = (%col.getDataBlock().max[%ammoName]) + AmmoPack.max[%ammoName]; + else + %aMax = %col.getDataBlock().max[%ammoName]; + } + else + %aMax = %col.getDataBlock().max[%ammoName]; + + if(%col.inv[%ammoName] < %aMax) + { + if( %obj.ammoStore $= "" ) + %obj.ammoStore = $AmmoIncrement[ %ammoName ]; + + %col.incInventory(%ammoName, %obj.ammoStore); + serverPlay3D(ItemPickupSound, %col.getTransform()); + %obj.respawn(); + if (%col.client > 0) + messageClient(%col.client, 'MsgItemPickup', '\c0You picked up %1.', %data.pickUpName); + } + } +} + +function GrenadeThrown::onCollision(%data, %obj, %col) +{ + // nothing you can do now... +} + +function HandInventory::onCollision(%data, %obj, %col) +{ + // %data = datablock of object; %obj = object number + // %col = thing that collided with object (hopefully a player) + if (%col.getDataBlock().className $= Armor) + { + %ammoName = %data.getName(); + %ammoStore = %col.inv[%ammoName]; + + // if player has ammo pack, increase max amount of ammo + if(%col.getMountedImage($BackpackSlot) != 0) + { + if(%col.getMountedImage($BackpackSlot).getName() $= "AmmoPackImage") + %aMax = (%col.getDataBlock().max[%ammoName]) + AmmoPack.max[%ammoName]; + else + %aMax = %col.getDataBlock().max[%ammoName]; + } + else + %aMax = %col.getDataBlock().max[%ammoName]; + + if(%data.isGrenade) + { + // it's a grenade -- see if it matches the type the player is carrying + %pgType = "None"; + for(%x = 0; $InvGrenade[%x] !$= ""; %x++) + { + %gren = $NameToInv[$InvGrenade[%x]]; + if(%col.inv[%gren] > 0) + { + %pgType = %gren; + break; + } + } + if((%pgType $= "None") || (%pgType $= %ammoName)) + { + // player either has no grenades or this type of grenades -- OK to pick up more + %canPickup = true; + } + else + { + // player has a different kind of grenade -- don't pick this kind up + %canPickup = false; + } + } + else + %canPickup = true; + + if(%canPickup) + { + if(%col.inv[%ammoName] < %aMax) + { + //------------------------------------------------------------------------------------------- + // z0dd - ZOD, 5/8/02. Don't allow player to pickup full ammo if they tossed less than full. + //%col.incInventory(%ammoName, $AmmoIncrement[%ammoName]); + if( %obj.ammoStore $= "" ) + %obj.ammoStore = $AmmoIncrement[ %ammoName ]; + %col.incInventory(%ammoName, %obj.ammoStore); + // End z0dd - ZOD + //------------------------------------------------------------------------------------------- + + serverPlay3D(ItemPickupSound, %col.getTransform()); + %obj.respawn(); + if (%col.client > 0) + messageClient(%col.client, 'MsgItemPickup', '\c0You picked up %1.', %data.pickUpName); + } + } + } +} + +//-------------------------------------- Specific turret functions + +function SentryTurret::onAdd(%data, %obj) +{ + Parent::onAdd(%data, %obj); + + //error("error"); + %obj.mountImage(%data.barrel, 0, true); +} + +function TurretDeployedCamera::onAdd(%this, %obj) +{ + Parent::onAdd(%this, %obj); + %obj.mountImage(DeployableCameraBarrel, 0, true); + %obj.setRechargeRate(%this.rechargeRate); + %obj.setAutoFire(false); // z0ddm0d: Server crash fix related to controlable cameras +} + +function TurretDeployedCamera::onDestroyed(%this, %obj, %prevState) +{ + if (%obj.isRemoved) + return; + %obj.isRemoved = true; + Parent::onDestroyed(%this, %obj, %prevState); + $TeamDeployedCount[%obj.team, DeployedCamera]--; + // doesn't seem to delete itself, so... + remDSurface(%obj); + %obj.schedule(500, "delete"); +} + +function ScoutFlyer::onTrigger(%data, %obj, %trigger, %state) +{ + // data = ScoutFlyer datablock + // obj = ScoutFlyer object number + // trigger = 0 for "fire", 1 for "jump", 3 for "thrust" + // state = 1 for firing, 0 for not firing + if(%trigger == 0) + { + switch (%state) { + case 0: + %obj.fireWeapon = false; + %obj.setImageTrigger(2, false); + %obj.setImageTrigger(3, false); + case 1: + %obj.fireWeapon = true; + if(%obj.nextWeaponFire == 2) { + %obj.setImageTrigger(2, true); + %obj.setImageTrigger(3, false); + } + else { + %obj.setImageTrigger(2, false); + %obj.setImageTrigger(3, true); + } + } + } +} + +function ScoutFlyer::playerDismounted(%data, %obj, %player) +{ + %obj.fireWeapon = false; + %obj.setImageTrigger(2, false); + %obj.setImageTrigger(3, false); + setTargetSensorGroup(%obj.getTarget(), %obj.team); + + if( %player.client.observeCount > 0 ) + resetObserveFollow( %player.client, true ); +} + +function ScoutChaingunImage::onFire(%data,%obj,%slot) +{ + // obj = ScoutFlyer object number + // slot = 2 + + Parent::onFire(%data,%obj,%slot); + %obj.nextWeaponFire = 3; + schedule(%data.fireTimeout, 0, "fireNextGun", %obj); +} + +function ScoutChaingunPairImage::onFire(%data,%obj,%slot) +{ + // obj = ScoutFlyer object number + // slot = 3 + + Parent::onFire(%data,%obj,%slot); + %obj.nextWeaponFire = 2; + schedule(%data.fireTimeout, 0, "fireNextGun", %obj); +} + +function fireNextGun(%obj) +{ + if(%obj.fireWeapon) + { + if(%obj.nextWeaponFire == 2) + { + %obj.setImageTrigger(2, true); + %obj.setImageTrigger(3, false); + } + else + { + %obj.setImageTrigger(2, false); + %obj.setImageTrigger(3, true); + } + } + else + { + %obj.setImageTrigger(2, false); + %obj.setImageTrigger(3, false); + } +} + +function ScoutChaingunImage::onTriggerDown(%this, %obj, %slot) +{ +} + +function ScoutChaingunImage::onTriggerUp(%this, %obj, %slot) +{ +} + +function ScoutChaingunImage::onMount(%this, %obj, %slot) +{ +// %obj.setImageAmmo(%slot,true); +} + +function ScoutChaingunPairImage::onMount(%this, %obj, %slot) +{ +// %obj.setImageAmmo(%slot,true); +} + +function ScoutChaingunImage::onUnmount(%this,%obj,%slot) +{ +} + +function ScoutChaingunPairImage::onUnmount(%this,%obj,%slot) +{ +} + + +function BomberTurret::onDamage(%data, %obj) +{ + %newDamageVal = %obj.getDamageLevel(); + if(%obj.lastDamageVal !$= "") + if(isObject(%obj.getObjectMount()) && %obj.lastDamageVal > %newDamageVal) + %obj.getObjectMount().setDamageLevel(%newDamageVal); + %obj.lastDamageVal = %newDamageVal; +} + +function BomberTurret::damageObject(%this, %targetObject, %sourceObject, %position, %amount, %damageType ,%vec, %client, %projectile) +{ + //If vehicle turret is hit then apply damage to the vehicle + %vehicle = %targetObject.getObjectMount(); + if(%vehicle) + %vehicle.getDataBlock().damageObject(%vehicle, %sourceObject, %position, %amount, %damageType, %vec, %client, %projectile); +} + +function VehicleTurret::onEndSequence(%data, %obj, %thread) +{ + if($DeployThread == %thread) + %obj.stopThread($DeployThread); +} + +function BomberTurret::onTrigger(%data, %obj, %trigger, %state) +{ + //error("onTrigger: trigger = " @ %trigger @ ", state = " @ %state); + //error("obj = " @ %obj @ ", class " @ %obj.getClassName()); + switch (%trigger) + { + case 0: + %obj.fireTrigger = %state; + if(%obj.selectedWeapon == 1) + { + %obj.setImageTrigger(4, false); + if(%obj.getImageTrigger(6)) + { + %obj.setImageTrigger(6, false); + ShapeBaseImageData::deconstruct(%obj.getMountedImage(6), %obj); + } + if(%state) + %obj.setImageTrigger(2, true); + else + %obj.setImageTrigger(2, false); + } + else if(%obj.selectedWeapon == 2) + { + %obj.setImageTrigger(2, false); + if(%obj.getImageTrigger(6)) + { + %obj.setImageTrigger(6, false); + ShapeBaseImageData::deconstruct(%obj.getMountedImage(6), %obj); + } + if(%state) + %obj.setImageTrigger(4, true); + else + %obj.setImageTrigger(4, false); + } + else + { + %obj.setImageTrigger(2, false); + %obj.setImageTrigger(4, false); + if(%state) + %obj.setImageTrigger(6, true); + else + { + %obj.setImageTrigger(6, false); + BomberTargetingImage::deconstruct(%obj.getMountedImage(6), %obj); + } + } + + case 2: + if(%state) + { + %obj.getDataBlock().playerDismount(%obj); + } + } +} + +function BomberTurret::playerDismount(%data, %obj) +{ + //Passenger Exiting + %obj.fireTrigger = 0; + %obj.setImageTrigger(2, false); + %obj.setImageTrigger(4, false); + if(%obj.getImageTrigger(6)) + { + %obj.setImageTrigger(6, false); + ShapeBaseImageData::deconstruct(%obj.getMountedImage(6), %obj); + } + %client = %obj.getControllingClient(); + %client.player.isBomber = false; + commandToClient(%client, 'endBomberSight'); +// %client.player.setControlObject(%client.player); + %client.player.mountVehicle = false; +// %client.player.getDataBlock().doDismount(%client.player); + if(%client.player.getState() !$= "Dead") + %client.player.mountImage(%client.player.lastWeapon, $WeaponSlot); + setTargetSensorGroup(%obj.getTarget(), 0); + setTargetNeverVisMask(%obj.getTarget(), 0xffffffff); +} + +//function BomberTurret::getHudNum(%data, %num) +//{ +// if(%num == 1) +// return 0; +// else +// return 4; +//} + +function AIAimingTurretBarrel::onFire(%this,%obj,%slot) +{ +} + +function BomberBombImage::onUnmount(%this,%obj,%slot) +{ +} + +function BomberBombPairImage::onUnmount(%this,%obj,%slot) +{ +} + +function BomberTurretBarrel::firePair(%this, %obj, %slot) +{ + %obj.setImageTrigger( 3, true); +} + +function BomberTurretBarrelPair::stopFire(%this, %obj, %slot) +{ + %obj.setImageTrigger( 3, false); +} + +function BomberTurretBarrelPair::onMount(%this, %obj, %slot) +{ +// %obj.setImageAmmo(%slot,true); +} + +function BomberTurretBarrel::onMount(%this, %obj, %slot) +{ +// %obj.setImageAmmo(%slot,true); +} + +function BomberBombImage::firePair(%this, %obj, %slot) +{ + %obj.setImageTrigger( 5, true); +} + +function BomberBombPairImage::stopFire(%this, %obj, %slot) +{ + %obj.setImageTrigger( 5, false); +} + +function BomberBombPairImage::onMount(%this, %obj, %slot) +{ +// %obj.setImageAmmo(%slot,true); +} + +function BomberBombImage::onMount(%this, %obj, %slot) +{ +} + +function BomberBombImage::onUnmount(%this,%obj,%slot) +{ +} + +function BomberBombPairImage::onUnmount(%this,%obj,%slot) +{ +} + +function MobileTurretBase::onAdd(%this, %obj) +{ + Parent::onAdd(%this, %obj); + setTargetSensorGroup(%obj.target, %obj.team); + //setTargetNeverVisMask(%obj.target, 0xffffffff); +} + +function MobileTurretBase::onDamage(%data, %obj) +{ + %newDamageVal = %obj.getDamageLevel(); + if(%obj.lastDamageVal !$= "") + if(isObject(%obj.getObjectMount()) && %obj.lastDamageVal > %newDamageVal) + %obj.getObjectMount().setDamageLevel(%newDamageVal); + %obj.lastDamageVal = %newDamageVal; +} + +function MobileTurretBase::damageObject(%this, %targetObject, %sourceObject, %position, %amount, %damageType ,%vec, %client, %projectile) +{ + //If vehicle turret is hit then apply damage to the vehicle + %vehicle = %targetObject.getObjectMount(); + if(%vehicle) + %vehicle.getDataBlock().damageObject(%vehicle, %sourceObject, %position, %amount, %damageType, %vec, %client, %projectile); +} + +function MobileTurretBase::onEndSequence(%data, %obj, %thread) +{ + //Used so that the parent wont be called.. +} + +function AssaultPlasmaTurret::onDamage(%data, %obj) +{ + %newDamageVal = %obj.getDamageLevel(); + if(%obj.lastDamageVal !$= "") + if(isObject(%obj.getObjectMount()) && %obj.lastDamageVal > %newDamageVal) + %obj.getObjectMount().setDamageLevel(%newDamageVal); + %obj.lastDamageVal = %newDamageVal; +} + +function AssaultPlasmaTurret::damageObject(%this, %targetObject, %sourceObject, %position, %amount, %damageType ,%vec, %client, %projectile) +{ + //If vehicle turret is hit then apply damage to the vehicle + %vehicle = %targetObject.getObjectMount(); + if(%vehicle) + %vehicle.getDataBlock().damageObject(%vehicle, %sourceObject, %position, %amount, %damageType, %vec, %client, %projectile); +} + +function AssaultPlasmaTurret::onTrigger(%data, %obj, %trigger, %state) +{ + switch (%trigger) { + case 0: + %obj.fireTrigger = %state; + if(%obj.selectedWeapon == 1) + { + %obj.setImageTrigger(4, false); + if(%state) + %obj.setImageTrigger(2, true); + else + %obj.setImageTrigger(2, false); + } + else + { + %obj.setImageTrigger(2, false); + if(%state) + %obj.setImageTrigger(4, true); + else + %obj.setImageTrigger(4, false); + } + case 2: + if(%state) + { + %obj.getDataBlock().playerDismount(%obj); + } + } +} + +function AssaultPlasmaTurret::playerDismount(%data, %obj) +{ + //Passenger Exiting + %obj.fireTrigger = 0; + %obj.setImageTrigger(2, false); + %obj.setImageTrigger(4, false); + %client = %obj.getControllingClient(); +// %client.setControlObject(%client.player); + %client.player.mountImage(%client.player.lastWeapon, $WeaponSlot); + %client.player.mountVehicle = false; + setTargetSensorGroup(%obj.getTarget(), 0); + setTargetNeverVisMask(%obj.getTarget(), 0xffffffff); +// %client.player.getDataBlock().doDismount(%client.player); +} + +//function AssaultPlasmaTurret::getHudNum(%data, %num) +//{ +// if(%num == 1) +// return 1; +// else +// return 3; +//} + + +// ------------------------------------------ +// camera functions +// ------------------------------------------ + +$CameraDeployTime = 1000; +$CameraDeployCheckMax = 6; +$CameraMinVelocity = 0.1; + +function CameraGrenadeThrown::onThrow(%this, %gren) +{ + // schedule a check to see if the camera is at rest but not deployed + %gren.checkCount = 0; + %gren.velocCheck = %this.schedule($CameraDeployTime, "checkCameraDeploy", %gren); +} + +function CameraGrenadeThrown::onStickyCollision(%data, %obj) +{ + cancel(%obj.velocCheck); + %pos = %obj.getLastStickyPos(); + %norm = %obj.getLastStickyNormal(); + + %intAngle = getTerrainAngle(%norm); // staticShape.cs + %rotAxis = vectorNormalize(vectorCross(%norm, "0 0 1")); + if (getWord(%norm, 2) == 1 || getWord(%norm, 2) == -1) + %rotAxis = vectorNormalize(vectorCross(%norm, "0 1 0")); + + %rotation = %rotAxis @ " " @ %intAngle; + %dcSucc = activateCamera(%pos, %rotation, %obj.sourceObject, %obj.sourceObject.team); + if(%dcSucc == 0) + messageClient(%obj.sourceObject.client, 'MsgDeployFailed', '\c2Your team\'s control network has reached its capacity for this item.~wfx/misc/misc.error.wav'); + %obj.schedule(50,"delete"); +} + +function CameraGrenadeThrown::checkCameraDeploy(%this, %gren) +{ + %gren.checkCount++; + if(VectorLen(%gren.getVelocity()) < $CameraMinVelocity) + { + // camera has come to rest but not deployed -- probably on a staticshape (station, gen, etc) + // no resolution, so get rid of it + %gren.schedule(50, "delete"); + } + else if(%gren.checkCount >= $CameraDeployCheckMax) + { + // camera's still moving but it's been check several times -- it was thrown from too great + // a height or off the edge of the world -- delete it + %gren.schedule(50, "delete"); + } + else + { + // check back in a little while + %gren.velocCheck = %this.schedule($CameraDeployTime, "checkCameraDeploy", %gren); + } +} + +function activateCamera(%position, %rotation, %sourceObj, %team) +{ + if($TeamDeployedCount[%team, DeployedCamera] >= $TeamDeployableMax[DeployedCamera]) + { + // team has too many cameras deployed already, don't deploy this one + return 0; + } + %dCam = new Turret() + { + dataBlock = "TurretDeployedCamera"; + team = %team; + needsNoPower = true; + owner = %sourceObj.client; + ownerHandle = %sourceObj.client.handle; + position = %position; + rotation = %rotation; + }; + addToDeployGroup(%dCam); + + if(%dCam.getTarget() != -1) + setTargetSensorGroup(%dCam.getTarget(), %team); + + %dCam.playAudio($DeploySound, CameraGrenadeAttachSound); + %dCam.deploy(); + %dCam.playThread($AmbientThread, "ambient"); + + // increment team's deployed count for cameras + $TeamDeployedCount[%team, DeployedCamera]++; + return 1; +} + +function FlareGrenade::onUse(%this, %obj) +{ + // a stripped-down version of HandInventory::onUse from weapons.cs + if(Game.handInvOnUse(%data, %obj)) { + %obj.decInventory(%this, 1); + %p = new FlareProjectile() { + dataBlock = FlareGrenadeProj; + initialDirection = %obj.getEyeVector(); + initialPosition = getBoxCenter(%obj.getWorldBox()); + sourceObject = %obj; + sourceSlot = 0; + }; + FlareSet.add(%p); + MissionCleanup.add(%p); + serverPlay3D(GrenadeThrowSound, getBoxCenter(%obj.getWorldBox())); + %p.schedule(6000, "delete"); + // miscellaneous grenade-throwing cleanup stuff + %obj.lastThrowTime[%data] = getSimTime(); + %obj.throwStrength = 0; + } +} + +// uncomment when explosion type can be set from script (dont want underwater explosion here) +//function grenadeOnEnterLiquid(%data, %obj, %coverage, %type, %flash) +//{ +// // 4: Lava +// // 5: Hot Lava +// // 6: Crusty Lava +// if(%type >=4 && %type <= 6) +// { +// if(%obj.getDamageState() !$= "Destroyed") +// { +// cancel(%obj.detThread); +// if(%flash) +// detonateFlashGrenade(%obj); +// else +// detonateGrenade(%obj); +// return(true); +// } +// } +// +// // flash grenades do not ignore quicksand +// if((%type == 7) && !%flash) +// return(true); +// +// return(false); +//} + +function GrenadeThrown::onThrow(%this, %gren) +{ + AIGrenadeThrown(%gren); + %gren.detThread = schedule(1500, %gren, "detonateGrenade", %gren); +} + +//function GrenadeThrown::onEnterLiquid(%data, %obj, %coverage, %type) +//{ +// if(!grenadeOnEnterLiquid(%data, %obj, %coverage, %type, false)) +// Parent::onEnterLiquid(%data, %obj, %coverage, %type); +//} + +function ConcussionGrenadeThrown::onThrow(%this, %gren) +{ + AIGrenadeThrown(%gren); + %gren.detThread = schedule(2000, %gren, "detonateGrenade", %gren); +} + +//function ConcussionGrenadeThrown::onEnterLiquid(%data, %obj, %coverage, %type) +//{ +// if(!grenadeOnEnterLiquid(%data, %obj, %coverage, %type, false)) +// Parent::onEnterLiquid(%data, %obj, %coverage, %type); +//} + +function detonateGrenade(%obj) +{ + %obj.setDamageState(Destroyed); + %data = %obj.getDataBlock(); + RadiusExplosion( %obj, %obj.getPosition(), %data.damageRadius, %data.indirectDamage, + %data.kickBackStrength, %obj.sourceObject, %data.radiusDamageType); + %obj.schedule(500,"delete"); +} + +function FlashGrenadeThrown::onThrow(%this, %gren) +{ + %gren.detThread = schedule(2000, %gren, "detonateFlashGrenade", %gren); +} + +//function FlashGrenadeThrown::onEnterLiquid(%data, %obj, %coverage, %type) +//{ +// if(!grenadeOnEnterLiquid(%data, %obj, %coverage, %type, true)) +// Parent::onEnterLiquid(%data, %obj, %coverage, %type); +//} + +function detonateFlashGrenade(%hg) +{ + %maxWhiteout = %hg.getDataBlock().maxWhiteout; + %thrower = %hg.sourceObject.client; + %hg.setDamageState(Destroyed); + %hgt = %hg.getTransform(); + %plX = firstword(%hgt); + %plY = getWord(%hgt, 1); + %plZ = getWord(%hgt, 2); + %pos = %plX @ " " @ %plY @ " " @ %plZ; + //all this stuff below ripped from projectiles.cs + + InitContainerRadiusSearch(%pos, 100.0, $TypeMasks::PlayerObjectType | + $TypeMasks::TurretObjectType); + + while ((%damage = containerSearchNext()) != 0) + { + %dist = containerSearchCurrDist(); + + %eyeXF = %damage.getEyeTransform(); + %epX = firstword(%eyeXF); + %epY = getWord(%eyeXF, 1); + %epZ = getWord(%eyeXF, 2); + %eyePos = %epX @ " " @ %epY @ " " @ %epZ; + %eyeVec = %damage.getEyeVector(); + + // Make sure we can see the thing... + if (ContainerRayCast(%eyePos, %pos, $TypeMasks::TerrainObjectType | + $TypeMasks::InteriorObjectType | + $TypeMasks::StaticObjectType, %damage) !$= "0") + { + continue; + } + + %distFactor = 1.0; + if (%dist >= 100) + %distFactor = 0.0; + else if (%dist >= 20) { + %distFactor = 1.0 - ((%dist - 20.0) / 80.0); + } + + %dif = VectorNormalize(VectorSub(%pos, %eyePos)); + %dot = VectorDot(%eyeVec, %dif); + + %difAcos = mRadToDeg(mAcos(%dot)); + %dotFactor = 1.0; + if (%difAcos > 60) + %dotFactor = ((1.0 - ((%difAcos - 60.0) / 120.0)) * 0.2) + 0.3; + else if (%difAcos > 45) + %dotFactor = ((1.0 - ((%difAcos - 45.0) / 15.0)) * 0.5) + 0.5; + + %totalFactor = %dotFactor * %distFactor; + + %prevWhiteOut = %damage.getWhiteOut(); + + if(!%prevWhiteOut) + if(!$teamDamage) + { + if(%damage.client != %thrower && %damage.client.team == %thrower.team) + messageClient(%damage.client, 'teamWhiteOut', '\c1You were hit by %1\'s whiteout grenade.', getTaggedString(%thrower.name)); + } + + %whiteoutVal = %prevWhiteOut + %totalFactor; + if(%whiteoutVal > %maxWhiteout) + { + //error("whitout at max"); + %whiteoutVal = %maxWhiteout; + } + + %damage.setWhiteOut( %whiteoutVal ); + } + %hg.schedule( 500, "delete" ); +} + +// ---------------------------------------------- +// mine functions +// ---------------------------------------------- + + +function MineDeployed::onThrow(%this, %mine, %thrower) +{ + %mine.armed = false; + %mine.damaged = 0; + %mine.detonated = false; + %mine.depCount = 0; + %mine.theClient = %thrower.client; + schedule(1500, %mine, "deployMineCheck", %mine, %thrower); +} + +function deployMineCheck(%mineObj, %player) +{ + if(%mineObj.depCount > %mineObj.getDatablock().maxDepCount) + explodeMine(%mineObj, true); + + // wait until the mine comes to rest + if(%mineObj.getVelocity() $= "0 0 0") + { + // 2-second delay before mine is armed -- let deploy thread play out etc. + schedule(%mineObj.getDatablock().armTime, %mineObj, "armDeployedMine", %mineObj); + + + // check for other deployed mines in the vicinity + InitContainerRadiusSearch(%mineObj.getWorldBoxCenter(), %mineObj.getDatablock().spacing, $TypeMasks::ItemObjectType); + while((%itemObj = containerSearchNext()) != 0) + { + if(%itemObj == %mineObj) + continue; + %ioType = %itemObj.getDatablock().getName(); + if(%ioType $= "MineDeployed") + schedule(100, %mineObj, "explodeMine", %mineObj, true); + else + continue; + } + // play "deploy" thread + %mineObj.playThread(0, "deploy"); + serverPlay3D(MineDeploySound, %mineObj.getTransform()); + %mineTeam = %mineObj.sourceObject.team; + $TeamDeployedCount[%mineTeam, MineDeployed]++; + if($TeamDeployedCount[%mineTeam, MineDeployed] > $TeamDeployableMax[MineDeployed]) + { + messageClient( %player.client, '', 'Maximum allowable mines deployed.' ); + schedule(100, %mineObj, "explodeMine", %mineObj, true); + } + else + { + //start the thread that keeps checking for objects near the mine... + mineCheckVicinity(%mineObj); + + //let the AI know *after* it's come to rest... + AIDeployMine(%mineObj); + + //let the game know there's a deployed mine + Game.notifyMineDeployed(%mineObj); + } + } + else + { + //schedule this deploy check again a little later + %mineObj.depCount++; + schedule(500, %mineObj, "deployMineCheck", %mineObj, %player); + } +} + +function armDeployedMine(%mine) +{ + %mine.armed = true; +} + +function mineCheckVicinity(%mine) +{ + // this function is called after the mine has been deployed. It will check the + // immediate area around the mine (2.5 meters at present) for players or vehicles + // passing by, and detonate if any are found. This is to extend the range of the + // mine so players don't have to collide with them to set them off. + + // don't bother to check if mine isn't armed yet + if(%mine.armed) + // don't keep checking if mine is already detonating + if(!%mine.boom) + { + // the actual check for objects in the area + %mineLoc = %mine.getWorldBoxCenter(); + %masks = $TypeMasks::PlayerObjectType | $TypeMasks::VehicleObjectType; + %detonateRange = %mine.getDatablock().proximity; + + InitContainerRadiusSearch(%mineLoc, %detonateRange, %masks); + while((%tgt = containerSearchNext()) != 0) + { + %mine.detonated = true; + schedule(50, %mine, "explodeMine", %mine, false); + break; + } + } + // if nothing set off the mine, schedule another check + if(!%mine.detonated) + schedule(300, %mine, "mineCheckVicinity", %mine); +} + +function MineDeployed::onCollision(%data, %obj, %col) +{ + // don't detonate if mine isn't armed yet + if(!%obj.armed) + return; + + // don't detonate if mine is already detonating + if(%obj.boom) + return; + + //check to see what it is that collided with the mine + %struck = %col.getClassName(); + if(%struck $= "Player" || %struck $= "WheeledVehicle" || %struck $= "FlyingVehicle") + { + //error("Mine detonated due to collision with #"@%col@" ("@%struck@"); armed = "@%obj.armed); + explodeMine(%obj, false); + } +} + +function explodeMine(%mo, %noDamage) +{ + %mo.noDamage = %noDamage; + %mo.setDamageState(Destroyed); +} + +function MineDeployed::damageObject(%data, %targetObject, %sourceObject, %position, %amount, %damageType) +{ + if(!%targetObject.armed) + return; + + if(%targetObject.boom) + return; + + %targetObject.damaged += %amount; + + if(%targetObject.damaged >= %data.maxDamage) + { + %targetObject.setDamageState(Destroyed); + } +} + +function MineDeployed::onDestroyed(%data, %obj, %lastState) +{ + if (%obj.isRemoved) + return; + %obj.isRemoved = true; + %obj.boom = true; + %mineTeam = %obj.team; + $TeamDeployedCount[%mineTeam, MineDeployed]--; + // %noDamage is a boolean flag -- don't want to set off all other mines in + // vicinity if there's a "mine overload", so apply no damage/impulse if true + if(!%obj.noDamage) + RadiusExplosion(%obj, %obj.getPosition(), %data.damageRadius, %data.indirectDamage, + %data.kickBackStrength, %obj.sourceObject, %data.radiusDamageType); + + %obj.schedule(600, "delete"); +} \ No newline at end of file diff --git a/scripts/weapons.cs b/scripts/weapons.cs new file mode 100644 index 0000000..9d8af74 --- /dev/null +++ b/scripts/weapons.cs @@ -0,0 +1,384 @@ +$HandInvThrowTimeout = 0.8 * 1000; // 1/2 second between throwing grenades or mines + +// z0dd - ZOD, 9/13/02. Added global array for serverside weapon reticles and "visible" +$WeaponsHudData[0, bitmapName] = "gui/hud_blaster"; +$WeaponsHudData[0, itemDataName] = "Blaster"; +//$WeaponsHudData[0, ammoDataName] = ""; +$WeaponsHudData[0, reticle] = "gui/ret_blaster"; +$WeaponsHudData[0, visible] = "true"; +$WeaponsHudData[1, bitmapName] = "gui/hud_plasma"; +$WeaponsHudData[1, itemDataName] = "Plasma"; +$WeaponsHudData[1, ammoDataName] = "PlasmaAmmo"; +$WeaponsHudData[1, reticle] = "gui/ret_plasma"; +$WeaponsHudData[1, visible] = "true"; +$WeaponsHudData[2, bitmapName] = "gui/hud_chaingun"; +$WeaponsHudData[2, itemDataName] = "Chaingun"; +$WeaponsHudData[2, ammoDataName] = "ChaingunAmmo"; +$WeaponsHudData[2, reticle] = "gui/ret_chaingun"; +$WeaponsHudData[2, visible] = "true"; +$WeaponsHudData[3, bitmapName] = "gui/hud_disc"; +$WeaponsHudData[3, itemDataName] = "Disc"; +$WeaponsHudData[3, ammoDataName] = "DiscAmmo"; +$WeaponsHudData[3, reticle] = "gui/ret_disc"; +$WeaponsHudData[3, visible] = "true"; +$WeaponsHudData[4, bitmapName] = "gui/hud_grenlaunch"; +$WeaponsHudData[4, itemDataName] = "GrenadeLauncher"; +$WeaponsHudData[4, ammoDataName] = "GrenadeLauncherAmmo"; +$WeaponsHudData[4, reticle] = "gui/ret_grenade"; +$WeaponsHudData[4, visible] = "true"; +$WeaponsHudData[5, bitmapName] = "gui/hud_sniper"; +$WeaponsHudData[5, itemDataName] = "SniperRifle"; +//$WeaponsHudData[5, ammoDataName] = ""; +$WeaponsHudData[5, reticle] = "gui/hud_ret_sniper"; +$WeaponsHudData[5, visible] = "false"; +$WeaponsHudData[6, bitmapName] = "gui/hud_elfgun"; +$WeaponsHudData[6, itemDataName] = "ELFGun"; +//$WeaponsHudData[6, ammoDataName] = ""; +$WeaponsHudData[6, reticle] = "gui/ret_elf"; +$WeaponsHudData[6, visible] = "true"; +$WeaponsHudData[7, bitmapName] = "gui/hud_mortor"; +$WeaponsHudData[7, itemDataName] = "Mortar"; +$WeaponsHudData[7, ammoDataName] = "MortarAmmo"; +$WeaponsHudData[7, reticle] = "gui/ret_mortor"; +$WeaponsHudData[7, visible] = "true"; +$WeaponsHudData[8, bitmapName] = "gui/hud_missiles"; +$WeaponsHudData[8, itemDataName] = "MissileLauncher"; +$WeaponsHudData[8, ammoDataName] = "MissileLauncherAmmo"; +$WeaponsHudData[8, reticle] = "gui/ret_missile"; +$WeaponsHudData[8, visible] = "true"; +// WARNING!!! If you change the weapon index of the targeting laser, +// you must change the HudWeaponInvBase::addWeapon function to test +// for the new value! +$WeaponsHudData[9, bitmapName] = "gui/hud_targetlaser"; +$WeaponsHudData[9, itemDataName] = "TargetingLaser"; +//$WeaponsHudData[9, ammoDataName] = ""; +$WeaponsHudData[9, reticle] = "gui/hud_ret_targlaser"; +$WeaponsHudData[9, visible] = "false"; +$WeaponsHudData[10, bitmapName] = "gui/hud_shocklance"; +$WeaponsHudData[10, itemDataName] = "ShockLance"; +//$WeaponsHudData[10, ammoDataName] = ""; +$WeaponsHudData[10, reticle] = "gui/hud_ret_shocklance"; +$WeaponsHudData[10, visible] = "false"; + +// TR2 weapons +$WeaponsHudData[11, bitmapName] = "gui/hud_disc"; +$WeaponsHudData[11, itemDataName] = "TR2Disc"; +$WeaponsHudData[11, ammoDataName] = "TR2DiscAmmo"; +$WeaponsHudData[11, reticle] = "gui/ret_disc"; +$WeaponsHudData[11, visible] = "true"; + +$WeaponsHudData[12, bitmapName] = "gui/hud_grenlaunch"; +$WeaponsHudData[12, itemDataName] = "TR2GrenadeLauncher"; +$WeaponsHudData[12, ammoDataName] = "TR2GrenadeLauncherAmmo"; +$WeaponsHudData[12, reticle] = "gui/ret_grenade"; +$WeaponsHudData[12, visible] = "true"; + +$WeaponsHudData[13, bitmapName] = "gui/hud_chaingun"; +$WeaponsHudData[13, itemDataName] = "TR2Chaingun"; +$WeaponsHudData[13, ammoDataName] = "TR2ChaingunAmmo"; +$WeaponsHudData[13, reticle] = "gui/ret_chaingun"; +$WeaponsHudData[13, visible] = "true"; + +$WeaponsHudData[14, bitmapName] = "gui/hud_targetlaser"; +$WeaponsHudData[14, itemDataName] = "TR2GoldTargetingLaser"; +$WeaponsHudData[14, reticle] = "gui/hud_ret_targlaser"; +$WeaponsHudData[14, visible] = "false"; + +$WeaponsHudData[15, bitmapName] = "gui/hud_targetlaser"; +$WeaponsHudData[15, itemDataName] = "TR2SilverTargetingLaser"; +$WeaponsHudData[15, reticle] = "gui/hud_ret_targlaser"; +$WeaponsHudData[15, visible] = "false"; + +$WeaponsHudData[16, bitmapName] = "gui/hud_shocklance"; +$WeaponsHudData[16, itemDataName] = "TR2ShockLance"; +$WeaponsHudData[16, reticle] = "gui/hud_ret_shocklance"; +$WeaponsHudData[16, visible] = "false"; + +$WeaponsHudData[17, bitmapName] = "gui/hud_mortor"; +$WeaponsHudData[17, itemDataName] = "TR2Mortar"; +$WeaponsHudData[17, ammoDataName] = "TR2MortarAmmo"; +$WeaponsHudData[17, reticle] = "gui/ret_mortor"; +$WeaponsHudData[17, visible] = "true"; + +$WeaponsHudData[18, bitmapName] = "gui/hud_shocklance"; +$WeaponsHudData[18, itemDataName] = "ConstructionTool"; +//$WeaponsHudData[18, ammoDataName] = ""; +$WeaponsHudData[18, reticle] = "gui/hud_ret_sniper"; +$WeaponsHudData[18, visible] = "false"; + +$WeaponsHudData[19, bitmapName] = "gui/hud_blaster"; +$WeaponsHudData[19, itemDataName] = "NerfGun"; +//$WeaponsHudData[19, ammoDataName] = ""; +$WeaponsHudData[19, reticle] = "gui/ret_blaster"; +$WeaponsHudData[19, visible] = "true"; + +$WeaponsHudData[20, bitmapName] = "gui/hud_grenlaunch"; +$WeaponsHudData[20, itemDataName] = "NerfBallLauncher"; +$WeaponsHudData[20, ammoDataName] = "NerfBallLauncherAmmo"; +$WeaponsHudData[20, reticle] = "gui/ret_grenade"; +$WeaponsHudData[20, visible] = "true"; + +$WeaponsHudData[21, bitmapName] = "gui/hud_chaingun"; +$WeaponsHudData[21, itemDataName] = "SuperChaingun"; +$WeaponsHudData[21, ammoDataName] = "SuperChaingunAmmo"; +$WeaponsHudData[21, reticle] = "gui/ret_chaingun"; +$WeaponsHudData[21, visible] = "true"; + +//[most] give some recticles to new weapons 'eh? +$WeaponsHudData[22, bitmapName] = "gui/hud_grenlaunch"; +$WeaponsHudData[22, itemDataName] = "TransGun"; +$WeaponsHudData[22, reticle] = "gui/hud_ret_sniper"; +$WeaponsHudData[22, visible] = "true"; + +$WeaponsHudData[23, bitmapName] = "gui/hud_grenlaunch"; +$WeaponsHudData[23, itemDataName] = "TractorGun"; +$WeaponsHudData[23, reticle] = "gui/ret_grenade"; +$WeaponsHudData[23, visible] = "true"; + +$WeaponsHudData[24, bitmapName] = "gui/hud_grenlaunch"; +$WeaponsHudData[24, itemDataName] = "MergeTool"; +$WeaponsHudData[24, reticle] = "gui/ret_mortor"; +$WeaponsHudData[24, visible] = "true"; + +$WeaponsHudCount = 25; +//[most] + +$AmmoIncrement[PlasmaAmmo] = 10; +$AmmoIncrement[ChaingunAmmo] = 25; +$AmmoIncrement[DiscAmmo] = 5; +$AmmoIncrement[GrenadeLauncherAmmo] = 5; +$AmmoIncrement[MortarAmmo] = 5; +$AmmoIncrement[MissileLauncherAmmo] = 2; +$AmmoIncrement[Mine] = 3; +$AmmoIncrement[Grenade] = 5; +$AmmoIncrement[FlashGrenade] = 5; +$AmmoIncrement[FlareGrenade] = 5; +$AmmoIncrement[ConcussionGrenade] = 5; +$AmmoIncrement[RepairKit] = 1; + +// ------------------------------------------------------------------- +// z0dd - ZOD, 4/17/02. Addition. Ammo pickup fix, these were missing. +$AmmoIncrement[CameraGrenade] = 2; +$AmmoIncrement[Beacon] = 1; + +$AmmoIncrement[NerfBallLauncherAmmo]= 5; +$AmmoIncrement[SuperChaingunAmmo] = 250; + +//---------------------------------------------------------------------------- +// Weapons scripts +//-------------------------------------- + +// --- Mounting weapons +exec("scripts/weapons/blaster.cs"); +exec("scripts/weapons/plasma.cs"); +exec("scripts/weapons/chaingun.cs"); +exec("scripts/weapons/disc.cs"); +exec("scripts/weapons/grenadeLauncher.cs"); +exec("scripts/weapons/sniperRifle.cs"); +exec("scripts/weapons/ELFGun.cs"); +exec("scripts/weapons/mortar.cs"); +exec("scripts/weapons/missileLauncher.cs"); +exec("scripts/weapons/targetingLaser.cs"); +exec("scripts/weapons/shockLance.cs"); +exec("scripts/weapons/constructionTool.cs"); +exec("scripts/weapons/nerfGun.cs"); +exec("scripts/weapons/nerfBallLauncher.cs"); +exec("scripts/weapons/superChaingun.cs"); +exec("scripts/weapons/modifiertool.cs"); +// --- Throwing weapons +exec("scripts/weapons/mine.cs"); +exec("scripts/weapons/grenade.cs"); +exec("scripts/weapons/flashGrenade.cs"); +exec("scripts/weapons/flareGrenade.cs"); +exec("scripts/weapons/concussionGrenade.cs"); +exec("scripts/weapons/cameraGrenade.cs"); + +//---------------------------------------------------------------------------- + +function Weapon::onUse(%data, %obj) +{ + if(Game.weaponOnUse(%data, %obj)) + if (%obj.getDataBlock().className $= Armor) + %obj.mountImage(%data.image, $WeaponSlot); +} + +function WeaponImage::onMount(%this,%obj,%slot) +{ + //MES -- is call below useful at all? + //Parent::onMount(%this, %obj, %slot); + if(%obj.getClassName() !$= "Player") + return; + + //messageClient(%obj.client, 'MsgWeaponMount', "", %this, %obj, %slot); + // Looks arm position + if (%this.armthread $= "") + { + %obj.setArmThread(look); + } + else + { + %obj.setArmThread(%this.armThread); + } + + // Initial ammo state + if(%obj.getMountedImage($WeaponSlot).ammo !$= "") + if (%obj.getInventory(%this.ammo)) + %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 WeaponImage::onUnmount(%this,%obj,%slot) +{ + %obj.client.setWeaponsHudActive(%this.item, 1); + %obj.client.setAmmoHudCount(-1); + commandToClient(%obj.client,'removeReticle'); + // try to avoid running around with sniper/missile arm thread and no weapon + %obj.setArmThread(look); + Parent::onUnmount(%this, %obj, %slot); +} + +function Ammo::onInventory(%this,%obj,%amount) +{ + // Loop through and make sure the images using this ammo have + // their ammo states set. + for (%i = 0; %i < 8; %i++) { + %image = %obj.getMountedImage(%i); + if (%image > 0) + { + if (isObject(%image.ammo) && %image.ammo.getId() == %this.getId()) + %obj.setImageAmmo(%i,%amount != 0); + } + } + ItemData::onInventory(%this,%obj,%amount); + // Uh, don't update the hud ammo counters if this is a corpse...that's bad. + if ( %obj.getClassname() $= "Player" && %obj.getState() !$= "Dead" ) + { + %obj.client.setWeaponsHudAmmo(%this.getName(), %amount); + if(%obj.getMountedImage($WeaponSlot).ammo $= %this.getName()) + %obj.client.setAmmoHudCount(%amount); + } +} + +function Weapon::onInventory(%this,%obj,%amount) +{ + if(Game.weaponOnInventory(%this, %obj, %amount)) + { + // Do not update the hud if this object is a corpse: + if ( %obj.getState() !$= "Dead" ) + %obj.client.setWeaponsHudItem(%this.getName(), 0, 1); + ItemData::onInventory(%this,%obj,%amount); + // if a player threw a weapon (which means that player isn't currently + // holding a weapon), set armthread to "no weapon" + // MES - taken out to avoid v-menu animation problems (bug #4749) + //if((%amount == 0) && (%obj.getClassName() $= "Player")) + // %obj.setArmThread(looknw); + } +} + +function Weapon::onPickup(%this, %obj, %shape, %amount) +{ + // If player doesn't have a weapon in hand, use this one... + if ( %shape.getClassName() $= "Player" + && %shape.getMountedImage( $WeaponSlot ) == 0 ) + %shape.use( %this.getName() ); +} + +function HandInventory::onInventory(%this,%obj,%amount) +{ + // prevent console errors when throwing ammo pack + if(%obj.getClassName() $= "Player") + %obj.client.setInventoryHudAmount(%this.getName(), %amount); + ItemData::onInventory(%this,%obj,%amount); +} + +function HandInventory::onUse(%data, %obj) +{ + // %obj = player %data = datablock of what's being thrown + if(Game.handInvOnUse(%data, %obj)) + { + //AI HOOK - If you change the %throwStren, tell Tinman!!! + //Or edit aiInventory.cs and search for: use(%grenadeType); + + %tossTimeout = getSimTime() - %obj.lastThrowTime[%data]; + if(%tossTimeout < $HandInvThrowTimeout) + return; + + %throwStren = %obj.throwStrength; + + %obj.decInventory(%data, 1); + %thrownItem = new Item() + { + dataBlock = %data.thrownItem; + sourceObject = %obj; + }; + MissionCleanup.add(%thrownItem); + + // throw it + %eye = %obj.getEyeVector(); + %vec = vectorScale(%eye, (%throwStren * 20.0)); + + // add a vertical component to give it a better arc + %dot = vectorDot("0 0 1", %eye); + if(%dot < 0) + %dot = -%dot; + %vec = vectorAdd(%vec, vectorScale("0 0 4", 1 - %dot)); + + // add player's velocity + %vec = vectorAdd(%vec, vectorScale(%obj.getVelocity(), 0.4)); + %pos = getBoxCenter(%obj.getWorldBox()); + + + %thrownItem.sourceObject = %obj; + %thrownItem.team = %obj.team; + %thrownItem.setTransform(%pos); + + %thrownItem.applyImpulse(%pos, %vec); + %thrownItem.setCollisionTimeout(%obj); + serverPlay3D(GrenadeThrowSound, %pos); + %obj.lastThrowTime[%data] = getSimTime(); + + %thrownItem.getDataBlock().onThrow(%thrownItem, %obj); + %obj.throwStrength = 0; + } +} + +function HandInventoryImage::onMount(%this,%obj,%slot) +{ + messageClient(%col.client, 'MsgHandInventoryMount', "", %this, %obj, %slot); + // Looks arm position + if (%this.armthread $= "") + %obj.setArmThread(look); + else + %obj.setArmThread(%this.armThread); + + // Initial ammo state + if (%obj.getInventory(%this.ammo)) + %obj.setImageAmmo(%slot,true); + + %obj.client.setWeaponsHudActive(%this.item); +} + +function Weapon::incCatagory(%data, %obj) +{ + // Don't count the targeting laser as a weapon slot: + if ( %data.getName() !$= "TargetingLaser" ) + %obj.weaponCount++; +} + +function Weapon::decCatagory(%data, %obj) +{ + // Don't count the targeting laser as a weapon slot: + if ( %data.getName() !$= "TargetingLaser" ) + %obj.weaponCount--; +} + +function SimObject::damageObject(%data) +{ + //function was added to reduce console err msg spam +} + diff --git a/scripts/weapons/constructionTool.cs b/scripts/weapons/constructionTool.cs new file mode 100644 index 0000000..73eca59 --- /dev/null +++ b/scripts/weapons/constructionTool.cs @@ -0,0 +1,1168 @@ +//-------------------------------------------------------------------------- +// Deconstruct Gun / Construction Tool +// Originally from Hammer Mod. Changed and redone for LuCiD MoD. +// Also Changed again and redone for Construction Mod. +// All changes made by LuCiD from LuCiD MoD & Mostlikely or JackTL from Construction Mod. + +$ReverseDeployItem[DeployedStationInventory] = InventoryDeployable; +$ReverseDeployItem[DeployedMotionSensor] = MotionSensorDeployable; +$ReverseDeployItem[DeployedPulseSensor] = PulseSensorDeployable; +$ReverseDeployItem[TurretDeployedOutdoor] = TurretOutdoorDeployable; +$ReverseDeployItem[TurretDeployedFloorIndoor] = TurretIndoorDeployable; +$ReverseDeployItem[TurretDeployedWallIndoor] = TurretIndoorDeployable; +$ReverseDeployItem[TurretDeployedCeilingIndoor] = TurretIndoorDeployable; +$ReverseDeployItem[TurretDeployedBase] = TurretBasePack; +$ReverseDeployItem[TurretDeployedCamera] = CameraGrenade; +$ReverseDeployItem[TelePadDeployedBase] = TelePadPack; +$ReverseDeployItem[DeployedSpine] = "poof spineDeployable"; +$ReverseDeployItem[DeployedWoodSpine] = "poof spineDeployable"; +$ReverseDeployItem[Deployedfloor] = "poof floorDeployable"; +$ReverseDeployItem[Deployedwall] = "poof wallDeployable"; +$ReverseDeployItem[Deployedwwall] = "poof wwallDeployable"; +$ReverseDeployItem[Deployedmspine] = "poof mspineDeployable"; +$ReverseDeployItem[DeployedDoor] = "poof DoorDeployable"; +$ReverseDeployItem[DeployedEnergizer] = EnergizerDeployable; +$ReverseDeployItem[Deployedmspinering] = "poof nothing"; +$ReverseDeployItem[DiscTurretDeployed] = DiscTurretDeployable; +$ReverseDeployItem[StationInventory] = LargeInventoryDeployable; +$ReverseDeployItem[DeployedJumpad] = JumpadDeployable; +$ReverseDeployItemDeployedBeacon = Beacon; +$ReverseDeployItem[DeployedLogoProjector] = LogoProjectorDeployable; +$ReverseDeployItem[LaserDeployed] = TurretLaserDeployable; +$ReverseDeployItem[MissileRackTurretDeployed] = TurretMissileRackDeployable; +$ReverseDeployItem[SensorMediumPulse] = MediumSensorDeployable; +$ReverseDeployItem[SensorLargePulse] = LargeSensorDeployable; +$ReverseDeployItem[DeployedLightBase] = "LightDeployable"; +$ReverseDeployItem[DeployedTripwire] = "TripwireDeployable"; +$ReverseDeployItem[DeployedEscapePod] = "EscapePodDeployable"; + +//Note this can also be in "pack".cs +//[most] +$ReverseDeployItem[Mpm_Anti_TurretDeployed] = "TurretMpm_Anti_Deployable"; +$ReverseDeployItem[DeployableVehiclePadBottom] = "VehiclePadPack"; +$ReverseDeployItem[DeployableVehiclePad] = "VehiclePadPack"; +$ReverseDeployItem[DeployableVehicleStation] = "VehiclePadPack"; +$ReverseDeployItem[DeployableVehiclePad2] = "VehiclePadPack"; +$ReverseDeployItem[PotPipe] = "poof"; +$ReverseDeployItem[EmitterDep] = "poof EmitterDepPack"; +$ReverseDeployItem[AudioDep] = "poof AudioDepPack"; +$ReverseDeployItem[DispenserDep] = "poof DispenserDepPack"; +$ReverseDeployItem[Mpm_Beacon_Ghost] = "poof"; +$ReverseDeployItem[DetonationDep] = "DetonationDepPack"; +$ReverseDeployItem[DetonationDepArm] = "DetonationDepPack"; +//[most] + +for (%i = 0;%i < 21;%i++) + $ReverseDeployItemDeployedForcefield[%i] = "ForceFieldDeployable"; +for (%i = 0;%i < 5;%i++) + $ReverseDeployItemDeployedGravityField[%i] = "GravityFieldDeployable"; +for (%i = 0;%i < 14;%i++) + $ReverseDeployItemDeployedTree[%i] = "TreeDeployable"; +for (%i = 0;%i < 13;%i++) + $ReverseDeployItemDeployedCrate[%i] = "CrateDeployable"; +for (%i = 0;%i < 16;%i++) + $ReverseDeployItemDeployedDecoration[%i] = "DecorationDeployable"; +// power +$ReverseDeployItem[GeneratorLarge] = GeneratorDeployable; +$ReverseDeployItem[SolarPanel] = SolarPanelDeployable; +$ReverseDeployItem[DeployedSwitch] = SwitchDeployable; +// DeconTarget +$ReverseDeployItem[DeployedLTarget] = "poof"; + + +//-------------------------------------------------------------------------- +// Sounds + +datablock EffectProfile(ConstructionToolSwitchEffect) { + effectname = "packs/packs.repairPackOn"; + minDistance = 2.5; + maxDistance = 2.5; +}; + +datablock EffectProfile(ConstructionToolFireEffect) { + effectname = "misc/downloading"; + minDistance = 2.5; + maxDistance = 5.0; +}; + +datablock AudioProfile(ConstructionToolSwitchSound) { + filename = "fx/packs/packs.repairPackOn.wav"; + description = AudioClosest3d; + preload = true; + effect = ConstructionToolSwitchEffect; +}; + +datablock AudioProfile(ConstructionToolFireSound) { + filename = "fx/misc/downloading.wav"; + description = CloseLooping3d; + preload = true; + effect = ConstructionToolFireEffect; +}; + +//-------------------------------------------------------------------------- +// Projectile + +datablock RepairProjectileData(ConstructionToolBeam) { + sound = ElfFireWetSound; + + beamRange = 100; + beamWidth = 0.15; + numSegments = 20; + texRepeat = 0.20; + blurFreq = 10.0; + blurLifetime = 1.0; + cutoffAngle = 25.0; + + textures[0] = "special/ELFLightning"; + textures[1] = "skins/flaregreen"; +}; + +//------------------------------------------------------------------------- +// shapebase datablocks + +datablock ItemData(ConstructionTool) { + className = Weapon; + catagory = "Spawn Items"; + shapeFile = "weapon_shocklance.dts"; + image = ConstructionToolImage; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 2; + rotate = true; + pickUpName = "a construction tool"; + + lightOnlyStatic = true; + lightType = "PulsingLight"; + lightColor = "0 1 0 1"; + lightTime = 1200; + lightRadius = 4; + + //computeCRC = true; + emap = true; +}; + +//-------------------------------------------------------------------------- +// Construction Tool + +datablock ShapeBaseImageData(ConstructionToolImage) { + shapeFile = "weapon_shocklance.dts"; + offset = "0 0 0"; + + item = ConstructionTool; + usesEnergy = true; + + minEnergy = 3; + + cutOffEnergy = 3.1; + emap = true; + + stateName[0] = "Activate"; + stateTransitionOnTimeout[0] = "ActivateReady"; + stateTimeoutValue[0] = 0.25; + stateSound[0] = ConstructionToolSwitchSound; + + stateName[1] = "ActivateReady"; + stateScript[1] = "onActivateReady"; + stateSpinThread[1] = Stop; + stateTransitionOnAmmo[1] = "Ready"; + stateTransitionOnNoAmmo[1] = "ActivateReady"; + + stateName[2] = "Ready"; + stateSpinThread[2] = Stop; + stateTransitionOnNoAmmo[2] = "Deactivate"; + stateTransitionOnTriggerDown[2] = "Validate"; + + stateName[3] = "Validate"; + stateTransitionOnTimeout[3] = "Validate"; + stateTimeoutValue[3] = 0.2; + stateEnergyDrain[3] = 3; + stateSpinThread[3] = SpinUp; + stateScript[3] = "onValidate"; + stateIgnoreLoadedForReady[3] = true; + stateTransitionOnLoaded[3] = "PerformAction"; + stateTransitionOnNoAmmo[3] = "Deactivate"; + stateTransitionOnTriggerUp[3] = "Deactivate"; + + stateName[4] = "PerformAction"; + stateSound[4] = ConstructionToolFireSound; + stateScript[4] = "onPerformAction"; + stateSpinThread[4] = FullSpeed; + stateAllowImageChange[4] = false; + stateSequence[4] = "activate"; + stateFire[4] = true; + stateEnergyDrain[4] = 16; + stateTimeoutValue[4] = 0.2; + stateTransitionOnTimeOut[4] = "PerformAction"; + stateTransitionOnNoAmmo[4] = "Deactivate"; + stateTransitionOnTriggerUp[4] = "Deactivate"; + stateTransitionOnNotLoaded[4] = "Validate"; + + stateName[5] = "Deactivate"; + stateScript[5] = "onDeactivate"; + stateSpinThread[5] = SpinDown; + stateSequence[5] = "activate"; + stateDirection[5] = false; + stateTimeoutValue[5] = 0.2; + stateTransitionOnTimeout[5] = "ActivateReady"; +}; + +function ConstructionToolImage::onActivate(%this,%obj,%slot) { +} + +function ConstructionToolImage::onActivateReady(%this,%obj,%slot) { + %obj.errMsgSent = false; +} + +function ConstructionToolImage::onValidate(%this,%obj,%slot) { + switch (%obj.constructionToolMode) { + case 0: // disassemble + onValidateDisassemble(%this,%obj,%slot); + case 1: // rotate + onValidateRotate(%this,%obj,%slot); + case 2: // advanced rotate + onValidateAdvancedRotate(%this,%obj,%slot); + case 3: // power management + onValidatePowerManagement(%this,%obj,%slot); + } +} + +function ConstructionToolImage::onPerformAction(%this,%obj,%slot) { + // this = ConstructionToolImage datablock + // obj = player wielding the construction tool + // slot = weapon slot + + if (%obj.getEnergyLevel() <= %this.cutOffEnergy) { + if (%obj.performing > 0) + stopPerforming(%obj); + return; + } + + // reset the flag that indicates an error message has been sent + %obj.errMsgSent = false; + + switch (%obj.constructionToolMode) { + case 0: // disassemble + onPerformDisassemble(%this,%obj,%slot); + case 1: // rotate + onPerformRotate(%this,%obj,%slot); + case 2: // advanced rotate + onPerformAdvancedRotate(%this,%obj,%slot); + case 3: // power management + onPerformPowerManagement(%this,%obj,%slot); + } +} + +function ConstructionToolImage::onDeactivate(%this,%obj,%slot) { + %obj.setImageTrigger(%slot, false); + if (%obj.performing > 0) { + stopPerforming(%obj); + messageClient(%player.client, 'msgClient', '\c2Construction Tool stopped.'); + } + %obj.errMsgSent = false; +} + +function ConstructionToolImage::onMount(%this,%obj,%slot) { + if (!$Host::TournamentMode) { + %curWeap = ( %obj.getMountedImage($WeaponSlot) == 0 ) ? "" : %obj.getMountedImage($WeaponSlot).getName().item.pickUpName; + BottomPrint(%obj.client, "Now using " @ %curWeap, 2, 1 ); + } + %obj.errMsgSent = false; + %obj.client.setWeaponsHudActive(%this.item); + %obj.usingConstructionTool = true; + if (!%obj.constructionToolMode) + %obj.constructionToolMode = 0; + if (!%obj.constructionToolMode2) + %obj.constructionToolMode2 = 0; + WeaponImage::onMount(%this,%obj,%slot); +} + +function ConstructionToolImage::onUnmount(%data, %obj, %slot) { + %obj.usingConstructionTool = false; + %obj.setImageTrigger(%slot, false); + if (%obj.performing > 0) { + stopPerforming(%obj); + messageClient(%player.client, 'msgClient', '\c2Construction Tool stopped.'); + } + %obj.errMsgSent = false; + Parent::deconstruct(%data, %obj, %slot); + WeaponImage::onUnmount(%data, %obj, %slot); +} + +function ConstructionTool::onPickup(%this, %obj, %shape, %amount) { + // created to prevent console errors +} + +// -------------------------------------------------------------------------------- +// Common functions +// -------------------------------------------------------------------------------- + +function startPerforming(%player) { + // %player = the player who was using the construction tool + %initialDirection = %player.getMuzzleVector($WeaponSlot); + %initialPosition = %player.getMuzzlePoint($WeaponSlot); + + //else + %performTime = 250; + + %player.performTime = %performTime; + // Temporary (hopefully) fix + %data = %player.performing.getDataBlock(); + %dataBlockName = %data.getName(); + if (%data.className !$= "forcefield" && %data.className !$= "gravityfield") { + %player.constructionToolProjectile = new RepairProjectile() { + dataBlock = ConstructionToolBeam; + initialDirection = %initialDirection; + initialPosition = %initialPosition; + sourceObject = %player; + sourceSlot = $WeaponSlot; + targetObject = %player.performing; + }; + MissionCleanup.add(%player.constructionToolProjectile); + } + %hTgt = %player.performing; + %hTgt.beingPerformed = true; +} + +function stopPerforming(%player) { + // %player = the player who was using the construction tool + if (%player.performing > 0) { + if (isObject(%player.constructionToolProjectile)) + %player.constructionToolProjectile.delete(); + } + %hTgt.beingPerformed = false; + %player.constructionToolProjectile = 0; + %player.performing = 0; + %player.performTime = 0; + %player.errMsgSent = true; + %player.setImageTrigger($WeaponSlot, false); + %player.setImageLoaded($WeaponSlot, false); + %client = %player.client; + if (%client.CampingThread) + cancel(%client.campingThread); + return; +} + +// -------------------------------------------------------------------------------- +// Disassemble functions +// -------------------------------------------------------------------------------- +function onValidateDisassemble(%this,%obj,%slot) { + %hGun = %obj.getMountedImage(%slot); + // muzVec is the vector coming from the construction tool's "muzzle" + %muzVec = %obj.getMuzzleVector(%slot); + // muzNVec = normalized muzVec + %muzNVec = VectorNormalize(%muzVec); + %beamRange = ConstructionToolBeam.beamRange; + // scale muzNVec to the range the repair beam can reach + %muzScaled = VectorScale(%muzNVec, %beamRange); + // muzPoint = the actual point of the gun's "muzzle" + %muzPoint = %obj.getMuzzlePoint(%slot); + // rangeEnd = muzzle point + length of beam + %rangeEnd = VectorAdd(%muzPoint, %muzScaled); + // search for just about anything that can be damaged as well as interiors + %searchMasks = $TypeMasks::InteriorObjectType | $TypeMasks::StaticShapeObjectType | $TypeMasks::VehicleObjectType | $TypeMasks::ForceFieldObjectType | $TypeMasks::ItemObjectType; + // search for objects within the beam's range that fit the masks above + %scanTarg = ContainerRayCast(%muzPoint, %rangeEnd, %searchMasks, %obj); + // screen out interiors + if (%scanTarg && !(%scanTarg.getType() & $TypeMasks::InteriorObjectType)) { + // a target in range was found + %hTgt = firstWord(%scanTarg); + // can it be dissed? is it already being tooled? + if ($ReverseDeployItem[%hTgt.getDataBlock().getName()] !$= "" && !%hTht.beingPerformed) + %canPerform = true; + // Only deconstruct deployed items, not base ones + %dataBlockName = %hTgt.getDataBlock().getName(); + if (%canPerform == true && ( + %dataBlockName $= "StationInventory" || + %dataBlockName $= "GeneratorLarge" || + %dataBlockName $= "SolarPanel" || + %dataBlockName $= "SensorMediumPulse" || + %dataBlockName $= "SensorLargePulse" + )) + if (%hTgt.deployed != true) + %canPerform = false; + if (%canPerform == true) { + // yes, it's disassembleable + if (%hTgt != %obj.performing) { + if (isObject(%obj.performing)) + stopPerforming(%obj); + %obj.performing = %hTgt; + startPerforming(%obj); + } + // setting imageLoaded to true sends us to deconstruct state (function onPerformAction) + %obj.setImageLoaded(%slot, true); + } + else { + // there is a target in range, but it's not disable + if (!%obj.errMsgSent) { + messageClient(%obj.client, 'msgClient', '\c2You can\'t deconstruct that.'); + %obj.errMsgSent = true; + } + // if player was Disassembling something, stop the disassembling -- we're done + if (%obj.performing > 0) + stopPerforming(%obj); + } + } + else { + // there is no target in range + if (!%obj.errMsgSent) { + // send an error message only once + messageClient(%obj.client, 'msgClient', '\c2No target to deconstruct.'); + %obj.errMsgSent = true; + } + } +} + +function onPerformDisassemble(%this,%obj,%slot) { + %target = %obj.performing; + if (!%target) { + // no target -- whoops! never mind + stopPerforming(%obj); + return; + } + if (%obj.constructionToolMode2 == 0) + %cascade = 0; + else + %cascade = 1; + %hGun = %obj.getMountedImage(%slot); + // muzVec is the vector coming from the construction tool's "muzzle" + %muzVec = %obj.getMuzzleVector(%slot); + // muzNVec = normalized muzVec + %muzNVec = VectorNormalize(%muzVec); + %beamRange = ConstructionToolBeam.beamRange; + // scale muzNVec to the range the repair beam can reach + %muzScaled = VectorScale(%muzNVec, %beamRange); + // muzPoint = the actual point of the gun's "muzzle" + %muzPoint = %obj.getMuzzlePoint(%slot); + // rangeEnd = muzzle point + length of beam + %rangeEnd = VectorAdd(%muzPoint, %muzScaled); + // search for just about anything that can be damaged as well as interiors + %searchMasks = $TypeMasks::InteriorObjectType | $TypeMasks::StaticShapeObjectType | $TypeMasks::VehicleObjectType | $TypeMasks::ForceFieldObjectType | $TypeMasks::ItemObjectType; + // search for objects within the beam's range that fit the masks above + %scanTarg = ContainerRayCast(%muzPoint, %rangeEnd, %searchMasks, %obj); + // screen out interiors + if (%scanTarg && !(%scanTarg.getType() & $TypeMasks::InteriorObjectType)) { + // a target in range was found + %hTgt = firstWord(%scanTarg); + // can it be dissed? is it already being tooled? + if ($ReverseDeployItem[%hTgt.getDataBlock().getName()] !$= "" && !%hTht.beingPerformed) + %canPerform = true; + // Only deconstruct deployed items, not base ones + %dataBlockName = %hTgt.getDataBlock().getName(); + if (%canPerform == true && ( + %dataBlockName $= "StationInventory" || + %dataBlockName $= "GeneratorLarge" || + %dataBlockName $= "SolarPanel" || + %dataBlockName $= "SensorMediumPulse" || + %dataBlockName $= "SensorLargePulse" + )) + if (%hTgt.deployed != true) + %canPerform = false; + if (%canPerform == true) { + // yes, it's disassembleable + if (%hTgt != %obj.performing) { // its not what we were originally dising + if (isObject(%obj.performing)) { + stopPerforming(%obj); + %obj.performing = %hTgt; + startPerforming(%obj); + } + } + else { // continue dising + %obj.performTime = %obj.performTime - 120; + if (%obj.performTime < 0) { // we have a dis! + if (%hTgt.isRemoved) + return; // Avoid duplicate disassemblies + if (%hTgt.team != %obj.team && !(%obj.client.isAdmin || %obj.client.isSuperAdmin)) { + messageClient(%obj.client, 'msgClient', '\c2Deconstruction failed! Wrong team!~wfx/powered/nexus_deny.wav'); + stopPerforming(%obj); + return; + } + if ($Host::OnlyOwnerDeconstruct == 1 && %hTgt.getOwner() != %obj.client && !(%obj.client.isAdmin || %obj.client.isSuperAdmin)) { + if (isObject(%hTgt.getOwner())) + messageClient(%obj.client, 'msgClient', '\c2Deconstruction failed! This belongs to %1!~wfx/powered/nexus_deny.wav', %hTgt.getOwner().nameBase); + else + messageClient(%obj.client, 'msgClient', '\c2Deconstruction failed! Not your stuff!~wfx/powered/nexus_deny.wav'); + stopPerforming(%obj); + return; + } + stopPerforming(%obj); + if (%cascade && $Host::OnlyOwnerCascade == 1 && %hTgt.getOwner() != %obj.client && !(%obj.client.isAdmin || %obj.client.isSuperAdmin)) + messageClient(%obj.client, 'msgClient', '\c2Cascade failed! Not your stuff!~wfx/powered/nexus_deny.wav'); + else { + if ((%hTgt.getType() & $TypeMasks::StaticShapeObjectType) && %hTgt.getDamageLeftPct() < (0.25 + ((getRandom() * 0.2) - 0.1))) { + if ($Host::InvincibleDeployables == 1 && %hTgt.getDamageLeftPct() <= 0) { +// %hTgt.setDamageLevel(%hTgt.getDataBlock().maxDamage - 0.01); + %hTgt.setDamageLevel(0); // Make sure we can blow it up.. + } + %hTgt.damageFailedDecon = true; + %hTgt.schedule(100,setDamageState,Destroyed); + messageClient(%obj.client, 'msgClient', '\c2Deconstruction failed!~wfx/powered/nexus_deny.wav'); + } + else { + %hTgt.getDataBlock().disassemble(%obj, %hTgt); // Run Item Specific code. + if (%cascade) + cascade(%hTgt,true); + if (%hTgt.getDataBlock().getName() $= "DeployedLTarget" && isObject(%hTgt.lMain)) + %revItem = %hTgt.lMain.getDataBlock().getName(); + else + %revItem = %hTgt.getDataBlock().getName(); + %newPack = $ReverseDeployItem[%revItem]; + if (getWord(%newPack,0) !$= "poof") { + %npack = new Item() { + dataBlock = %newPack; + }; + MissionCleanup.add(%npack); + %npack.schedulePop(); + if (%newPack $= "ForceFieldDeployable" || %newPack $= "GravityFieldDeployable" || %newPack $= "DecorationDeployable") + %pos = %hTgt.getWorldBoxCenter(); + else + %pos = %hTgt.getPosition(); + %npack.setTransform(getWords(%scanTarg,1,3) SPC "0 0 1" SPC (getRandom() * ($Pi * 2))); + } + } + } + } + } + } + } + else + stopPerforming(%obj); +} + +// -------------------------------------------------------------------------------- +// Rotate functions +// -------------------------------------------------------------------------------- + +function onValidateRotate(%this,%obj,%slot) { + %hGun = %obj.getMountedImage(%slot); + // muzVec is the vector coming from the construction tool's "muzzle" + %muzVec = %obj.getMuzzleVector(%slot); + // muzNVec = normalized muzVec + %muzNVec = VectorNormalize(%muzVec); + %beamRange = ConstructionToolBeam.beamRange; + // scale muzNVec to the range the repair beam can reach + %muzScaled = VectorScale(%muzNVec, %beamRange); + // muzPoint = the actual point of the gun's "muzzle" + %muzPoint = %obj.getMuzzlePoint(%slot); + // rangeEnd = muzzle point + length of beam + %rangeEnd = VectorAdd(%muzPoint, %muzScaled); + // search for just about anything that can be damaged as well as interiors + %searchMasks = $TypeMasks::InteriorObjectType | $TypeMasks::StaticShapeObjectType | $TypeMasks::VehicleObjectType | $TypeMasks::ForceFieldObjectType | $TypeMasks::ItemObjectType; + // search for objects within the beam's range that fit the masks above + %scanTarg = ContainerRayCast(%muzPoint, %rangeEnd, %searchMasks, %obj); + // screen out interiors + if (%scanTarg && !(%scanTarg.getType() & $TypeMasks::InteriorObjectType)) { + // a target in range was found + %hTgt = firstWord(%scanTarg); + // can it be rotated? is it already being tooled? + if ($ReverseDeployItem[%hTgt.getDataBlock().getName()] !$= "" && !%hTht.beingPerformed) + %canPerform = true; + // Only rotate deployed items, not base ones + %dataBlockName = %hTgt.getDataBlock().getName(); + if (%dataBlockName $= "DeployedLTarget" && !isObject(%hTgt.lMain)) + %canPerform = false; + if (%canPerform == true && ( + %dataBlockName $= "StationInventory" || + %dataBlockName $= "GeneratorLarge" || + %dataBlockName $= "SolarPanel" || + %dataBlockName $= "SensorMediumPulse" || + %dataBlockName $= "SensorLargePulse" + )) + if (%hTgt.deployed != true) + %canPerform = false; + if (%canPerform == true) { + // yes, it's rotatable + if (%hTgt != %obj.performing) { + if (isObject(%obj.performing)) + stopPerforming(%obj); + %obj.performing = %hTgt; + startPerforming(%obj); + } + // setting imageLoaded to true sends us to rotate state (function onPerformAction) + %obj.setImageLoaded(%slot, true); + } + else { + // there is a target in range, but it's not rotatable + if (!%obj.errMsgSent) { + messageClient(%obj.client, 'msgClient', '\c2You can\'t rotate that.'); + %obj.errMsgSent = true; + } + // if player was rotating something, stop the rotating -- we're done + if (%obj.performing > 0) + stopPerforming(%obj); + } + } + else { + // there is no target in range + if (!%obj.errMsgSent) { + // send an error message only once + messageClient(%obj.client, 'msgClient', '\c2No target to rotate.'); + %obj.errMsgSent = true; + } + } +} + +function onPerformRotate(%this,%obj,%slot) { + %target = %obj.performing; + if (!%target) { + // no target -- whoops! never mind + stopPerforming(%obj); + return; + } + if (%obj.constructionToolMode2 == 0) + %rotVal = 1; + else + %rotVal = -1; + %hGun = %obj.getMountedImage(%slot); + // muzVec is the vector coming from the construction tool's "muzzle" + %muzVec = %obj.getMuzzleVector(%slot); + // muzNVec = normalized muzVec + %muzNVec = VectorNormalize(%muzVec); + %beamRange = ConstructionToolBeam.beamRange; + // scale muzNVec to the range the repair beam can reach + %muzScaled = VectorScale(%muzNVec, %beamRange); + // muzPoint = the actual point of the gun's "muzzle" + %muzPoint = %obj.getMuzzlePoint(%slot); + // rangeEnd = muzzle point + length of beam + %rangeEnd = VectorAdd(%muzPoint, %muzScaled); + // search for just about anything that can be damaged as well as interiors + %searchMasks = $TypeMasks::InteriorObjectType | $TypeMasks::StaticShapeObjectType | $TypeMasks::VehicleObjectType | $TypeMasks::ForceFieldObjectType | $TypeMasks::ItemObjectType; + // search for objects within the beam's range that fit the masks above + %scanTarg = ContainerRayCast(%muzPoint, %rangeEnd, %searchMasks, %obj); + // screen out interiors + if (%scanTarg && !(%scanTarg.getType() & $TypeMasks::InteriorObjectType)) { + // a target in range was found + %hTgt = firstWord(%scanTarg); + // can it be rotated? is it already being tooled? + if ($ReverseDeployItem[%hTgt.getDataBlock().getName()] !$= "" && !%hTht.beingPerformed) + %canPerform = true; + // Only rotate deployed items, not base ones + %dataBlockName = %hTgt.getDataBlock().getName(); + if (%dataBlockName $= "DeployedLTarget" && !isObject(%hTgt.lMain)) + %canPerform = false; + if (%canPerform == true && ( + %dataBlockName $= "StationInventory" || + %dataBlockName $= "GeneratorLarge" || + %dataBlockName $= "SolarPanel" || + %dataBlockName $= "SensorMediumPulse" || + %dataBlockName $= "SensorLargePulse" + )) + if (%hTgt.deployed != true) + %canPerform = false; + if (%canPerform == true) { + // yes, it's rotatable + if (%hTgt != %obj.performing) { // its not what we were originally rotating + if (isObject(%obj.performing)) { + stopPerforming(%obj); + %obj.performing = %hTgt; + startPerforming(%obj); + } + } + else { // continue rotating + %obj.performTime = %obj.performTime - 120; + if (%obj.performTime < 0) { // we have a rot! + if (%hTgt.team != %obj.team && !(%obj.client.isAdmin || %obj.client.isSuperAdmin)) { + messageClient(%obj.client, 'msgClient', '\c2Rotate failed! Wrong team!~wfx/powered/nexus_deny.wav'); + stopPerforming(%obj); + return; + } + if ($Host::OnlyOwnerRotate == 1 && %hTgt.getOwner() != %obj.client && !(%obj.client.isAdmin || %obj.client.isSuperAdmin)) { + messageClient(%obj.client, 'msgClient', '\c2Rotate failed! Not your stuff!~wfx/powered/nexus_deny.wav'); + stopPerforming(%obj); + return; + } + stopPerforming(%obj); + %obj = firstWord(%scanTarg); + %vec1 = posFromRaycast(%scanTarg); + %vec2 = normalFromRaycast(%scanTarg); + pullObject(%obj,%vec1,%vec2,$Pi/8*%rotVal,"0 0 0"); + } + } + } + } + else + stopPerforming(%obj); +} + +// -------------------------------------------------------------------------------- +// Advanced rotate functions +// -------------------------------------------------------------------------------- + +function onValidateAdvancedRotate(%this,%obj,%slot) { + %m2 = %obj.constructionToolMode2; + if (%m2 == 2 || %m2 == 3 || %m2 == 4 || %m2 == 5) { + %obj.setImageLoaded(%slot, true); + return; + } + + %hGun = %obj.getMountedImage(%slot); + // muzVec is the vector coming from the construction tool's "muzzle" + %muzVec = %obj.getMuzzleVector(%slot); + // muzNVec = normalized muzVec + %muzNVec = VectorNormalize(%muzVec); + %beamRange = ConstructionToolBeam.beamRange; + // scale muzNVec to the range the repair beam can reach + %muzScaled = VectorScale(%muzNVec, %beamRange); + // muzPoint = the actual point of the gun's "muzzle" + %muzPoint = %obj.getMuzzlePoint(%slot); + // rangeEnd = muzzle point + length of beam + %rangeEnd = VectorAdd(%muzPoint, %muzScaled); + // search for just about anything that can be damaged as well as interiors + %searchMasks = $TypeMasks::InteriorObjectType | $TypeMasks::StaticShapeObjectType | $TypeMasks::VehicleObjectType | $TypeMasks::ForceFieldObjectType | $TypeMasks::ItemObjectType; + // search for objects within the beam's range that fit the masks above + %scanTarg = ContainerRayCast(%muzPoint, %rangeEnd, %searchMasks, %obj); + // screen out interiors + if (%scanTarg && !(%scanTarg.getType() & $TypeMasks::InteriorObjectType)) { + // a target in range was found + %hTgt = firstWord(%scanTarg); + // can it be selected? is it already being tooled? + if ($ReverseDeployItem[%hTgt.getDataBlock().getName()] !$= "" && !%hTht.beingPerformed) + %canPerform = true; + // Only select deployed items, not base ones + %dataBlockName = %hTgt.getDataBlock().getName(); + if (%dataBlockName $= "DeployedLTarget" && !isObject(%hTgt.lMain)) + %canPerform = false; + if (%canPerform == true && ( + %dataBlockName $= "StationInventory" || + %dataBlockName $= "GeneratorLarge" || + %dataBlockName $= "SolarPanel" || + %dataBlockName $= "SensorMediumPulse" || + %dataBlockName $= "SensorLargePulse" + )) + if (%hTgt.deployed != true) + %canPerform = false; + if (!$Host::AllowUnderground) { + if (%dataBlockName $= "TelePadDeployedBase") + %canPerform = false; + } + if (%canPerform == true) { + // yes, it's selectable + if (%hTgt != %obj.performing) { + if (isObject(%obj.performing)) + stopPerforming(%obj); + %obj.performing = %hTgt; + startPerforming(%obj); + } + // setting imageLoaded to true sends us to select state (function onPerformAction) + %obj.setImageLoaded(%slot, true); + } + else { + // there is a target in range, but it's not selectable + if (!%obj.errMsgSent) { + messageClient(%obj.client, 'msgClient', '\c2You can\'t select/rotate that.'); + %obj.errMsgSent = true; + } + // if player was selecting something, stop the selecting -- we're done + if (%obj.performing > 0) + stopPerforming(%obj); + } + } + else { + // there is no target in range + if (!%obj.errMsgSent) { + // send an error message only once + messageClient(%obj.client, 'msgClient', '\c2No target to select/rotate.'); + %obj.errMsgSent = true; + } + } +} + +function onPerformAdvancedRotate(%this,%obj,%slot) { + // Account for lag, and make gun a bit less trigger happy + %m2 = %obj.constructionToolMode2; + if (%m2 == 2 || %m2 == 3 || %m2 == 4 || %m2 == 5) { + if (getSimTime() < (%obj.constructionToolTime + 500)) + return; + } + else { + if (getSimTime() < (%obj.constructionToolTime + 500) && %obj.performTime < 0) + return; + } + %obj.constructionToolTime = getSimTime(); + + // Load rotation list + %list = %obj.rotList; + + // Validate list + %size = getWordCount(%list); + for(%id = 0; %id < %size; %id++) { + if (!isObject(getWord(%list,%id))) + %badIDs = %badIDs SPC %id; + } + %list = listDel(%list,trim(%badIDs)); + + if (!%list) // Is there a rotation list? + %list = %obj; // Set player as center. + + // Save list + %obj.rotList = %list; + + if (%obj.rotSpeed == 0) // So players can rotate without specifically setting rotSpeed + %obj.rotSpeed = 1; + + if (%obj.constructionToolMode2 == 2) { + %obj.rotSpeed++; + if (%obj.rotSpeed > 3) + %obj.rotSpeed = -3; + if (%obj.rotSpeed == 0) + %obj.rotSpeed = 1; + %mod = lev(%obj.rotSpeed) * 5 * mPow(3,mAbs(%obj.rotSpeed) -1); + bottomPrint(%obj.client,"Rotation speed set to:" SPC %mod SPC " degrees per tick",2,1); + return; + } + else if(%obj.constructionToolMode2 == 3) { + %angle =lev(%obj.rotSpeed) * 5 * mPow(3,mAbs(%obj.rotSpeed) -1) / 180 * $Pi; + %mod = lev(%obj.rotSpeed) * 5 * mPow(3,mAbs(%obj.rotSpeed) -1); + rotateSection(getWord(%list,0),%list,"0 0 1" SPC %angle); + %obj.constructionToolTime = %obj.constructionToolTime + (getWordCount(%list) * 100); + bottomPrint(%obj.client,getWordCount(%list) SPC "objects rotated" SPC %mod SPC " degrees (wait " @ mFloor((%obj.constructionToolTime - getSimTime()) / 1000) @ " seconds)",2,1); + return; + } + else if(%obj.constructionToolMode2 == 4) { + for(%id = 0; %id < getWordCount(%list); %id++) { + %obj = getWord(%list,%id); + %obj.startFade(400,%id * 100,0); + if (isObject(%obj.lMain)) + %obj.lMain.startFade(400,%id * 100,0); + } + bottomPrint(%obj.client,getWordCount(%list) SPC "objects selected including the rotation center",2,1); + return; + } + else if(%obj.constructionToolMode2 == 5) { + %list = ""; + %obj.rotList = %list; + bottomPrint(%obj.client,"All objects removed from rotation list - player set as rotation center",2,1); + return; + } + + %target = %obj.performing; + if (!%target) { + // no target -- whoops! never mind + stopPerforming(%obj); + return; + } + %hGun = %obj.getMountedImage(%slot); + // muzVec is the vector coming from the construction tool's "muzzle" + %muzVec = %obj.getMuzzleVector(%slot); + // muzNVec = normalized muzVec + %muzNVec = VectorNormalize(%muzVec); + %beamRange = ConstructionToolBeam.beamRange; + // scale muzNVec to the range the repair beam can reach + %muzScaled = VectorScale(%muzNVec, %beamRange); + // muzPoint = the actual point of the gun's "muzzle" + %muzPoint = %obj.getMuzzlePoint(%slot); + // rangeEnd = muzzle point + length of beam + %rangeEnd = VectorAdd(%muzPoint, %muzScaled); + // search for just about anything that can be damaged as well as interiors + %searchMasks = $TypeMasks::InteriorObjectType | $TypeMasks::StaticShapeObjectType | $TypeMasks::VehicleObjectType | $TypeMasks::ForceFieldObjectType | $TypeMasks::ItemObjectType; + // search for objects within the beam's range that fit the masks above + %scanTarg = ContainerRayCast(%muzPoint, %rangeEnd, %searchMasks, %obj); + // screen out interiors + if (%scanTarg && !(%scanTarg.getType() & $TypeMasks::InteriorObjectType)) { + // a target in range was found + %hTgt = firstWord(%scanTarg); + // can it be selected? is it already being tooled? + if ($ReverseDeployItem[%hTgt.getDataBlock().getName()] !$= "" && !%hTht.beingPerformed) + %canPerform = true; + // Only select deployed items, not base ones + %dataBlockName = %hTgt.getDataBlock().getName(); + if (%dataBlockName $= "DeployedLTarget" && !isObject(%hTgt.lMain)) + %canPerform = false; + if (%canPerform == true && ( + %dataBlockName $= "StationInventory" || + %dataBlockName $= "GeneratorLarge" || + %dataBlockName $= "SolarPanel" || + %dataBlockName $= "SensorMediumPulse" || + %dataBlockName $= "SensorLargePulse" + )) + if (%hTgt.deployed != true) + %canPerform = false; + if (!$Host::AllowUnderground) { + if (%dataBlockName $= "TelePadDeployedBase") + %canPerform = false; + } + if (%canPerform == true) { + // yes, it's selectable + if (%hTgt != %obj.performing) { // its not what we were originally selecting + if (isObject(%obj.performing)) { + stopPerforming(%obj); + %obj.performing = %hTgt; + startPerforming(%obj); + } + } + else { // continue selecting + %obj.performTime = %obj.performTime - 120; + if (%obj.performTime < 0) { // we have a select! + if (%hTgt.team != %obj.team && !(%obj.client.isAdmin || %obj.client.isSuperAdmin)) { + messageClient(%obj.client, 'msgClient', '\c2Select failed! Wrong team!~wfx/powered/nexus_deny.wav'); + stopPerforming(%obj); + return; + } + if ($Host::OnlyOwnerRotate == 1 && %hTgt.getOwner() != %obj.client && !(%obj.client.isAdmin || %obj.client.isSuperAdmin)) { + messageClient(%obj.client, 'msgClient', '\c2Select failed! Not your stuff!~wfx/powered/nexus_deny.wav'); + stopPerforming(%obj); + return; + } + if (%obj.constructionToolMode2 == 0) { + if (%hTgt == getWord(%list,0)) { // Is it already the center? + %list = listReplace(%list,%obj,0); // Replace player as center + bottomPrint(%obj.client,"Object deselected as center",2,1); + } + else { + // Remove it from the list if it was in the list to start with. + %loc = findWord(%list,%hTgt); + if (%loc !$= "") + %list = listDel(%list,%loc); + %list = listReplace(%list,%hTgt,0); // Replace player as center + bottomPrint(%obj.client,"Object selected as center",2,1); + } + %hTgt.startFade(400,%id * 100,0); + if (isObject(%hTgt.lMain)) + %hTgt.lMain.startFade(400,%id * 100,0); + } + else if (%obj.constructionToolMode2 == 1) { + if (%hTgt == getWord(%list,0)) + bottomPrint(%obj.client,"Object is already center of rotation",2,1); + else { + %loc = findWord(%list,%hTgt); + if (%loc !$= "") { // Is it already in the list? + %list = listDel(%list,%loc); + bottomPrint(%obj.client,"Object deselected",2,1); + } + else { + %tempList = %list; + %list = %tempList SPC %hTgt; + bottomPrint(%obj.client,"Object Selected",2,1); + } + } + %hTgt.startFade(400,%id * 100,0); + if (isObject(%hTgt.lMain)) + %hTgt.lMain.startFade(400,%id * 100,0); + } + } + } + } + } + else + stopPerforming(%obj); + %obj.rotList = %list; +} + +// -------------------------------------------------------------------------------- +// Power management functions +// -------------------------------------------------------------------------------- + +function onValidatePowerManagement(%this,%obj,%slot) { + + %m2 = %obj.constructionToolMode2; + if (%m2 == 1 || %m2 == 2) { + %obj.setImageLoaded(%slot, true); + return; + } + + %hGun = %obj.getMountedImage(%slot); + // muzVec is the vector coming from the construction tool's "muzzle" + %muzVec = %obj.getMuzzleVector(%slot); + // muzNVec = normalized muzVec + %muzNVec = VectorNormalize(%muzVec); + %beamRange = ConstructionToolBeam.beamRange; + // scale muzNVec to the range the repair beam can reach + %muzScaled = VectorScale(%muzNVec, %beamRange); + // muzPoint = the actual point of the gun's "muzzle" + %muzPoint = %obj.getMuzzlePoint(%slot); + // rangeEnd = muzzle point + length of beam + %rangeEnd = VectorAdd(%muzPoint, %muzScaled); + // search for just about anything that can be damaged as well as interiors + %searchMasks = $TypeMasks::InteriorObjectType | $TypeMasks::StaticShapeObjectType | $TypeMasks::VehicleObjectType | $TypeMasks::ForceFieldObjectType | $TypeMasks::ItemObjectType; + // search for objects within the beam's range that fit the masks above + %scanTarg = ContainerRayCast(%muzPoint, %rangeEnd, %searchMasks, %obj); + // screen out interiors + if (%scanTarg && !(%scanTarg.getType() & $TypeMasks::InteriorObjectType)) { + // a target in range was found + %hTgt = firstWord(%scanTarg); + // can it be used? is it already being tooled? + if ($ReverseDeployItem[%hTgt.getDataBlock().getName()] !$= "" && !%hTht.beingPerformed) + %canPerform = true; + // Only use deployed items, not base ones + %dataBlockName = %hTgt.getDataBlock().getName(); + if (%dataBlockName $= "DeployedLTarget" && !isObject(%hTgt.lMain)) + %canPerform = false; + if (%canPerform == true && ( + %dataBlockName $= "StationInventory" || + %dataBlockName $= "GeneratorLarge" || + %dataBlockName $= "SolarPanel" || + %dataBlockName $= "SensorMediumPulse" || + %dataBlockName $= "SensorLargePulse" + )) + if (%hTgt.deployed != true) + %canPerform = false; + if (%canPerform == true) { + // yes, it's usable + if (%hTgt != %obj.performing) { + if (isObject(%obj.performing)) + stopPerforming(%obj); + %obj.performing = %hTgt; + startPerforming(%obj); + } + // setting imageLoaded to true sends us to use state (function onPerformAction) + %obj.setImageLoaded(%slot, true); + } + else { + // there is a target in range, but it's not usable + if (!%obj.errMsgSent) { + messageClient(%obj.client, 'msgClient', '\c2You can\'t use that.'); + %obj.errMsgSent = true; + } + // if player was using something, stop it -- we're done + if (%obj.performing > 0) + stopPerforming(%obj); + } + } + else { + // there is no target in range + if (!%obj.errMsgSent) { + // send an error message only once + messageClient(%obj.client, 'msgClient', '\c2No target to use.'); + %obj.errMsgSent = true; + } + } +} + +function onPerformPowerManagement(%this,%obj,%slot) { + // Account for lag, and make gun a bit less trigger happy + %m2 = %obj.constructionToolMode2; + if (%m2 == 1 || %m2 == 2) { + if (getSimTime() < (%obj.constructionToolTime + 500)) + return; + } + else { + if (getSimTime() < (%obj.constructionToolTime + 500) && %obj.performTime < 0) + return; + } + %obj.constructionToolTime = getSimTime(); + + if (%obj.constructionToolMode2 == 1) { + %obj.powerFreq++; + if (%obj.powerFreq > upperPowerFreq(%obj)) + %obj.powerFreq = 1; + displayPowerFreq(%obj); + return; + } + else if (%obj.constructionToolMode2 == 2) { + %obj.powerFreq--; + if (%obj.powerFreq < 1) + %obj.powerFreq = upperPowerFreq(%obj); + displayPowerFreq(%obj); + return; + } + + %target = %obj.performing; + if (!%target) { + // no target -- whoops! never mind + stopPerforming(%obj); + return; + } + + %hGun = %obj.getMountedImage(%slot); + // muzVec is the vector coming from the construction tool's "muzzle" + %muzVec = %obj.getMuzzleVector(%slot); + // muzNVec = normalized muzVec + %muzNVec = VectorNormalize(%muzVec); + %beamRange = ConstructionToolBeam.beamRange; + // scale muzNVec to the range the repair beam can reach + %muzScaled = VectorScale(%muzNVec, %beamRange); + // muzPoint = the actual point of the gun's "muzzle" + %muzPoint = %obj.getMuzzlePoint(%slot); + // rangeEnd = muzzle point + length of beam + %rangeEnd = VectorAdd(%muzPoint, %muzScaled); + // search for just about anything that can be damaged as well as interiors + %searchMasks = $TypeMasks::InteriorObjectType | $TypeMasks::StaticShapeObjectType | $TypeMasks::VehicleObjectType | $TypeMasks::ForceFieldObjectType | $TypeMasks::ItemObjectType; + // search for objects within the beam's range that fit the masks above + %scanTarg = ContainerRayCast(%muzPoint, %rangeEnd, %searchMasks, %obj); + // screen out interiors + if (%scanTarg && !(%scanTarg.getType() & $TypeMasks::InteriorObjectType)) { + // a target in range was found + %hTgt = firstWord(%scanTarg); + // can it be used? is it already being tooled? + if ($ReverseDeployItem[%hTgt.getDataBlock().getName()] !$= "" && !%hTht.beingPerformed) + %canPerform = true; + // Only use deployed items, not base ones + %dataBlockName = %hTgt.getDataBlock().getName(); + if (%dataBlockName $= "DeployedLTarget" && !isObject(%hTgt.lMain)) + %canPerform = false; + if (%canPerform == true && ( + %dataBlockName $= "StationInventory" || + %dataBlockName $= "GeneratorLarge" || + %dataBlockName $= "SolarPanel" || + %dataBlockName $= "SensorMediumPulse" || + %dataBlockName $= "SensorLargePulse" + )) + if (%hTgt.deployed != true) + %canPerform = false; + if (%canPerform == true) { + // yes, it's usable + if (%hTgt != %obj.performing) { // its not what we were originally using + if (isObject(%obj.performing)) { + stopPerforming(%obj); + %obj.performing = %hTgt; + startPerforming(%obj); + } + } + else { // continue using + %obj.performTime = %obj.performTime - 120; + if (%obj.performTime < 0) { // we have a use! + if (%hTgt.team != %obj.team && !(%obj.client.isAdmin || %obj.client.isSuperAdmin)) { + messageClient(%obj.client, 'msgClient', '\c2Use failed! Wrong team!~wfx/powered/nexus_deny.wav'); + stopPerforming(%obj); + return; + } + if (%obj.constructionToolMode2 == 0) { + if (%hTgt.getDataBlock().className !$= "Generator") { + messageClient(%obj.client, 'msgClient', '\c2Use failed! Not a generator!~wfx/powered/nexus_deny.wav'); + stopPerforming(%obj); + return; + } + else { + %r = toggleGenerator(%hTgt); + %r1 = firstWord(%r); + %r2 = getTaggedString(getWord(%r,1)); + %r3 = getWord(%r,2); + if (%r1 == -2) + messageClient(%obj.client, 'msgClient', '\c2Use failed! %1 is damaged!~wfx/powered/nexus_deny.wav',%r2); + else if (%r1 == -3) + messageClient(%obj.client, 'msgClient', '\c2Must wait %1 seconds before toggling power state.',mCeil(%r3/1000)); + else if (%r1 == 1) + messageClient(%obj.client, 'msgClient', '\c2%1 switched off.',%r2); + else if (%r1 == 2) + messageClient(%obj.client, 'msgClient', '\c2%1 switched on.',%r2); + stopPerforming(%obj); + return; + } + } + if (%obj.constructionToolMode2 == 3) { +// if (%hTgt.powerFreq !$= "" || %hTgt.getDataBlock().needsPower) { + %numLines = 1; + if (%hTgt.powerFreq !$= "") + %msg = "Power frequency is " @ %hTgt.powerFreq @ ", power is " @ (%hTgt.isPowered() ? ((%hTgt.powerCount > 0) ? (%hTgt.powerCount) : "On") : "OFF"); + else + %msg = "Item does not have power frequency set"; + if (%hTgt.getOwner().nameBase !$= "") { + %numLines++; + %msg = %msg @ "\nThis belongs to " @ %hTgt.getOwner().nameBase; + } + if (%obj.client.isAdmin || %obj.client.isSuperAdmin) { + %numLines++; + %msg = %msg @ "\n [Owner Clientid]:" SPC %hTgt.getOwner() SPC "[Object id]:" SPC %htgt; + } + bottomPrint(%obj.client,%msg,2,%numLines); + stopPerforming(%obj); +// } + } + } + } + } + } + else + stopPerforming(%obj); + %obj.rotList = %list; +} diff --git a/scripts/weapons/dragonmissile.cs b/scripts/weapons/dragonmissile.cs new file mode 100644 index 0000000..305c35b --- /dev/null +++ b/scripts/weapons/dragonmissile.cs @@ -0,0 +1,547 @@ +$WeaponSettings1[MissileTransformer] = "9 -1 TractorGun"; +$WeaponSetting1[MissileTransformer,0] = "Travel Time: 1 second [35m]"; +$WeaponSetting1[MissileTransformer,1] = "Travel Time: 2 seconds [120m]"; +$WeaponSetting1[MissileTransformer,2] = "Travel Time: 3 seconds [255m]"; +$WeaponSetting1[MissileTransformer,3] = "Travel Time: 4 seconds [440m]"; +$WeaponSetting1[MissileTransformer,4] = "Travel Time: 5 seconds [675m]"; +$WeaponSetting1[MissileTransformer,5] = "Travel Time: 6 seconds [960m]"; +$WeaponSetting1[MissileTransformer,6] = "Travel Time: 7 seconds [1.3km]"; +$WeaponSetting1[MissileTransformer,7] = "Travel Time: 8 seconds [1.7km]"; +$WeaponSetting1[MissileTransformer,8] = "Travel Time: 9 seconds [2.1km]"; +$WeaponSetting1[MissileTransformer,9] = "Travel Time: 10 seconds [2.6km]"; + + +datablock ParticleData( D_GDebrisSmokeParticle ) +{ + dragCoeffiecient = 1.0; + gravityCoefficient = 0.0; + inheritedVelFactor = 0.2; + + lifetimeMS = 750; + lifetimeVarianceMS = 100; + + textureName = "particleTest"; + + useInvAlpha = true; + + spinRandomMin = -60.0; + spinRandomMax = 60.0; + + colors[0] = "0.4 0.4 0.4 1.0"; + colors[1] = "0.3 0.3 0.3 0.1"; + colors[2] = "0.0 0.0 0.0 0.0"; + sizes[0] = 1.1; + sizes[1] = 4.0; + sizes[2] = 3.0; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; +}; + +datablock ParticleEmitterData( D_GDebrisSmokeEmitter ) +{ + ejectionPeriodMS = 5; + periodVarianceMS = 1; + + ejectionVelocity = 2.0; // A little oomph at the back end + velocityVariance = 0.2; + + thetaMin = 0.0; + thetaMax = 0.0; + + particles = "D_GDebrisSmokeParticle"; +}; + + +datablock DebrisData(D_Debris) +{ + emitters[0] = D_GDebrisSmokeEmitter; + + explodeOnMaxBounce = true; + + elasticity = 0.4; + friction = 0.2; + + lifetime = 0.2; + lifetimeVariance = 1; + + numBounces = 10; +}; + + +datablock ParticleData(D_Dust) +{ + dragCoefficient = 1.0; + gravityCoefficient = -0.01; + inheritedVelFactor = 0.0; + constantAcceleration = 0.0; + lifetimeMS = 2000; + lifetimeVarianceMS = 100; + useInvAlpha = true; + spinRandomMin = -90.0; + spinRandomMax = 500.0; + textureName = "particleTest"; + colors[0] = "0.3 0.3 0.3 0.5"; + colors[1] = "0.3 0.3 0.3 0.5"; + colors[2] = "0.3 0.3 0.3 0.0"; + sizes[0] = 5.2; + sizes[1] = 7.6; + sizes[2] = 7.0; + times[0] = 0.0; + times[1] = 0.7; + times[2] = 1.0; +}; + +datablock ParticleEmitterData(D_DustEmitter) +{ + ejectionPeriodMS = 5; + periodVarianceMS = 0; + ejectionVelocity = 15.0; + velocityVariance = 0.0; + ejectionOffset = 0.0; + thetaMin = 85; + thetaMax = 85; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + lifetimeMS = 250; + particles = "D_Dust"; +}; + + +datablock ParticleData(D_ESmoke) +{ + dragCoeffiecient = 0.4; + gravityCoefficient = -0.5; // rises slowly + inheritedVelFactor = 0.025; + + lifetimeMS = 1750; + lifetimeVarianceMS = 0; + + textureName = "particleTest"; + + useInvAlpha = true; + spinRandomMin = -200.0; + spinRandomMax = 200.0; + + textureName = "special/Smoke/smoke_001"; + + colors[0] = "0.8 0.4 0.2 1.0"; + colors[1] = "0.5 0.3 0.1 1.0"; + colors[2] = "0.1 0.1 0.1 0.0"; + sizes[0] = 2.0; + sizes[1] = 6.0; + sizes[2] = 2.0; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; + +}; + +datablock ParticleEmitterData(D_ESmokeEmitter) +{ + ejectionPeriodMS = 5; + periodVarianceMS = 0; + + ejectionVelocity = 8.25; + velocityVariance = 0.25; + + thetaMin = 0.0; + thetaMax = 90.0; + + lifetimeMS = 250; + + particles = "D_ESmoke"; +}; + + + +datablock ParticleData(D_Sparks) +{ + dragCoefficient = 1; + gravityCoefficient = 0.0; + inheritedVelFactor = 0.2; + constantAcceleration = 0.0; + lifetimeMS = 500; + lifetimeVarianceMS = 350; + textureName = "special/bigspark"; + colors[0] = "0.56 0.36 0.26 1.0"; + colors[1] = "0.56 0.36 0.26 1.0"; + colors[2] = "1.0 0.36 0.26 0.0"; + sizes[0] = 2.5; + sizes[1] = 2.5; + sizes[2] = 2.75; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; + +}; + +datablock ParticleEmitterData(D_SparksEmitter) +{ + ejectionPeriodMS = 2; + periodVarianceMS = 0; + ejectionVelocity = 12; + velocityVariance = 6.75; + ejectionOffset = 0.0; + thetaMin = 0; + thetaMax = 60; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + orientParticles = true; + lifetimeMS = 100; + particles = "D_Sparks"; +}; + + + + + +datablock ExplosionData(D_Explosion) +{ + soundProfile = GrenadeExplosionSound; + + faceViewer = true; + explosionScale = "0.9 0.9 0.9"; + + debris = D_Debris; + debrisThetaMin = 10; + debrisThetaMax = 50; + debrisNum = 50; + debrisVelocity = 20.0; + debrisVelocityVariance = 10.0; + + emitter[0] = D_DustEmitter; + emitter[1] = D_ESmokeEmitter; + emitter[2] = D_SparksEmitter; + + shakeCamera = true; + camShakeFreq = "10.0 6.0 9.0"; + camShakeAmp = "20.0 20.0 20.0"; + camShakeDuration = 0.5; + camShakeRadius = 20.0; +}; + +datablock TracerProjectileData(LHE):Mpm_G_PR { + Explosion = "D_Explosion"; + }; + +function GameConnection::flukeattack(%cl) +{ +%image = %cl.player.getMountedImage(0); +if (!IsObject(%image)) + return ""; +%image.onFire(%cl.player,0); +} + +datablock ParticleData( LoadingP1 ) +{ + dragCoeffiecient = 0; + gravityCoefficient = 0.0; + inheritedVelFactor = -1.0; + constantAcceleration = -4; + lifetimeMS = 850; + lifetimeVarianceMS = 0; + windCoefficient = 0.0; + textureName = "flarebase"; + + useInvAlpha = false; + + spinRandomMin = 0.0; + spinRandomMax = 0.0; + + colors[0] = "0.20 0.20 1 1.0"; + colors[1] = "0.20 0.20 1 1.0"; + colors[2] = "0.20 0.20 1 1.0"; + colors[3] = "0.2 0.2 1 0.0"; + sizes[0] = 0.05; + sizes[1] = 0.1; + sizes[2] = 0.2; + sizes[3] = 0.8; + times[0] = 0.5; + times[1] = 0.7; + times[2] = 0.90; + times[3] = 1.0; +}; + + + +datablock ParticleEmitterData( LoadingE2 ) +{ + ejectionPeriodMS = 5; + periodVarianceMS = 1; + + ejectionVelocity = 1.7; // A little oomph at the back end + velocityVariance = 0.0; + ejectionoffset = 0.8; + thetaMin = 0.0; + thetaMax = 180.0; + phiReferenceVel = "0"; + phiVariance = "360"; + particles = "LoadingP1"; +}; + + +datablock ParticleData( Loading1P ) +{ + dragCoeffiecient = 0; + gravityCoefficient = 0.0; + inheritedVelFactor = -1.0; + constantAcceleration = -4; + lifetimeMS = 850; + lifetimeVarianceMS = 0; + windCoefficient = 0.0; + textureName = "flarebase"; + + useInvAlpha = false; + + spinRandomMin = 0.0; + spinRandomMax = 0.0; + + colors[0] = "0.20 0.20 1 1.0"; + colors[1] = "0.20 0.20 1 1.0"; + colors[2] = "0.20 0.20 1 1.0"; + colors[3] = "0.2 0.2 1 0.0"; + sizes[0] = 0.05; + sizes[1] = 0.1; + sizes[2] = 0.2; + sizes[3] = 0.8; + times[0] = 0.5; + times[1] = 0.7; + times[2] = 0.90; + times[3] = 1.0; +}; + + + +datablock ParticleEmitterData( Loading1E ) +{ + ejectionPeriodMS = 5; + periodVarianceMS = 1; + + ejectionVelocity = 1.7; // A little oomph at the back end + velocityVariance = 0.0; + ejectionoffset = 0.8; + thetaMin = 0.0; + thetaMax = 180.0; + phiReferenceVel = "0"; + phiVariance = "360"; + particles = "Loading1P"; +}; + + +datablock ParticleData( LoadingP ) +{ + dragCoeffiecient = 0; + gravityCoefficient = 0.0; + inheritedVelFactor = 0.0; + constantAcceleration = 0; + lifetimeMS = 70; + lifetimeVarianceMS = 0; + windCoefficient = 0.0; + textureName = "flarebase"; + + useInvAlpha = false; + + spinRandomMin = 0.0; + spinRandomMax = 0.0; + + colors[0] = "0.20 0.20 1 1.0"; + colors[1] = "0.20 0.20 1 1.0"; + colors[2] = "0.20 0.20 1 1.0"; + colors[3] = "0.2 0.2 1 0.0"; + sizes[0] = 0.9; + sizes[1] = 1; + sizes[2] = 1; + sizes[3] = 0.9; + times[0] = 0.25; + times[1] = 0.5; + times[2] = 0.75; + times[3] = 1.0; +}; + + + +datablock ParticleEmitterData( LoadingE ) +{ + ejectionPeriodMS = 10; + periodVarianceMS = 0; + + ejectionVelocity = 0.1; // A little oomph at the back end + velocityVariance = 0.0; + ejectionoffset = 1.5; + thetaMin = 0.0; + thetaMax = 5.0; + phiReferenceVel = "0"; + phiVariance = "360"; + particles = "LoadingP"; + orientParticles = false; + orientOnVelocity = false; +}; + + + +datablock SeekerProjectileData(TransformerMissile):ShoulderMissile +{ +casingShapeName = "weapon_missile_casement.dts"; + directDamage =0; + directDamageType = $DamageType::SuperChaingun; + + hasDamageRadius = False; + indirectDamage = 0; + damageRadius = 0; + radiusDamageType = $DamageType::SuperChaingun; + + //muzzleVelocity = 50; + maxVelocity = 800; + //turningSpeed = 0.0; + acceleration = 50; + exhaustEmitter = LoadingE; + exhaustTimeMs = 10000; + exhaustNodeName = "muzzlePoint1"; + lifetimems = 12000; +}; + +//make sure. +TransformerMissile.lifetimems = 12000; + +datablock ShapeBaseImageData(MissileTransformer):NerfBallLauncherImage +{ + className = WeaponImage; + shapeFile = "weapon_grenade_launcher.dts"; + item = TransGun; + usesEnergy = true; + fireEnergy = 50; + minEnergy = 50; + ammo = ""; + offset = "0 0 0"; + emap = true; + + projectile = TransformerMissile; + projectileType = SeekerProjectile; + + projectileSpread = 30.0 / 1000.0; + stateSound[3] = MissileFireSound; + +}; +datablock ItemData(TransGun) +{ + className = Weapon; + catagory = "Spawn Items"; + shapeFile = "weapon_energy.dts"; + image = MissileTransformer; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 2; + pickUpName = "a trasportation gun"; +}; + + +function TransformerMissile::onCollision(%data, %projectile, %targetObject, %modifier, %position, %normal) +{ +%client=%projectile.cl; +Cancel(%client.endobsch); +%client.player.setTransform(%position); +%client.player.schedule(100,blowup); // chunkOrama! +%client.player.schedule(100,scriptkill,$DamageType::Crash); +Parent::onCollision(%data, %projectile, %targetObject, %modifier, %position, %normal); +} + +function TransformerMissile::onExplode(%data, %proj, %pos, %mod) +{ +%client=%proj.cl; +Cancel(%client.endobsch); +%client.player.setTransform(%pos); +%client.player.schedule(100,blowup); // chunkOrama! +%client.player.schedule(100,scriptkill,$DamageType::Crash); +Parent::onExplode(%data, %proj, %pos, %mod); +} + +// Bot fun! +function MissileTransformer::onFire(%data,%obj,%slot) +{ +//parent::onFire(%data,%obj,%slot); +//%client = %obj.client; +//%p = TransformerMissile1.Create(%client.player.getMuzzlePoint(0),%client.player.getMuzzleVector(0),%client.player.getVelocity()); +testobs(%obj.client); +} + + + +function testobs(%client) +{ +%p = TransformerMissile.Create(%client.player.getMuzzlePoint(0),%client.player.getMuzzleVector(0),%client.player.getVelocity()); +%p.dir = %client.player.getMuzzleVector(0); +%p.rot = %client.player.getRotation(); +%p.cl = %client; + +%time = %client.player.weaponSet1+1; +if (%time $= "" || %time < 1 || %time > 10) + %time = 5; + +if(!isObject(%p)) + return""; + +if ( !isObject( %client.comCam ) ) + { + %client.comCam = new Camera() + { + dataBlock = CommanderCamera; + }; + MissionCleanup.add(%client.comCam); + } + //commandToClient(%client, 'ControlObjectResponse', true, getControlObjectType(%p,%client.player)); + //messageClient(%colObj.client, 'CloseHud', "", 'inventoryScreen'); + %client.comCam.setTransform(%p.getTransform()); + %client.comCam.setOrbitMode(%p,%p.getTransform(),0,10,-10); + + %client.setControlObject(%client.comCam); + %client.moveprojectile = %p; + commandToClient(%client, 'CameraAttachResponse', true); + %client.player.startfade(0,0,1); + if (isObject(%client.player.getobjectMount())) + %client.player.unmount(); + %client.player.setTransform(VectorAdd(%client.player.getTransform(),"0 0 -50000")); + schedule(750,0,"checkobs",%client); + + + %client.endobsch = schedule(%time*1000,0,"endobs",%client); +} + +function checkobs(%client) +{ +if (!isObject(%client.moveprojectile)) + { + %pos = %client.comCam.getTransform(); + Cancel(%client.endobsch); + %client.player.setTransform(%pos); + %client.player.schedule(100,blowup); // chunkOrama! + %client.player.schedule(100,scriptkill,$DamageType::Crash); + PlayExplosion(%pos,LHE,"0 0 1"); + return ""; + } +} + +function endobs(%client) +{ +if (!isObject(%client.moveprojectile)) + { + %pos = %client.comCam.getTransform(); + Cancel(%client.endobsch); + %client.player.setTransform(%pos); + %client.player.schedule(100,blowup); // chunkOrama! + %client.player.schedule(100,scriptkill,$DamageType::Crash); + PlayExplosion(%pos,LHE,"0 0 1"); + return ""; + } +%client.player.setTransform(getWords(%client.moveprojectile.getTransform(),0,2) SPC %client.moveporjectile.rot); +%client.player.startfade(0,0,0); +%client.player.setVelocity("0 0 0"); +%client.player.applyImpulse(%client.player.getTransform(),VectorScale(%client.moveprojectile.dir,20000)); +%client.setControlObject(%client.player); +%client.moveprojectile.delete(); + +//%client.comCam.delete(); +} diff --git a/scripts/weapons/modifiertool.cs b/scripts/weapons/modifiertool.cs new file mode 100644 index 0000000..554cd3a --- /dev/null +++ b/scripts/weapons/modifiertool.cs @@ -0,0 +1,707 @@ + +//Modifier Tool v001 +//Parts by Electricutioner and CaptnPower + +//Variables: +$ElecMod::MergeTool::Tolerance = 0.05; //how many meters of tolerance do we give the pieces that we merge. +$ElecMod::MergeTool::Timeout = 2; //how many seconds until a selection times out when using the tool + +datablock AudioProfile(chsingleshot) +{ + filename = "fx/vehicles/tank_chaingun.wav"; + description = AudioDefault3d; + preload = true; + effect = AssaultChaingunFireEffect; +}; +//Functions: +function MTMerge(%client, %piece1, %piece2) +{ + if (!MTCheckCompatability(%client, %piece1, %piece2)) + { + %piece1.setCloaked(false); + %piece2.setCloaked(false); + MTClearClientSelection(); + return; + } + %piece1.setCloaked(true); + %piece2.setCloaked(true); + schedule(100, 0, "MTScaleShiftMerge", %piece1, %piece2); + + if (isEventPending(%client.mergeschedule)) + { + cancel(%client.mergeschedule); + MTClearClientSelection(); + } + +} + +//This function checks if 4 corners of the objects are compatable. +function MTCheckCompatability(%client, %piece1, %piece2) +{ + //do the pieces exist? + if (!isObject(%piece1) || !isObject(%piece2)) + { + messageClient(%client, 'MsgClient', "\c2MT: A piece appears to be missing."); + return; + } + //check if the owners are the same + if (%piece1.owner != %client || %piece2.owner != %client) + { + //with an exemption of admins + if (!%client.isAdmin) + { + if (%piece1.ownerGUID != %client.guid || %piece2.ownerGUID != %client.guid) + { + messageClient(%client, 'MsgClient', "\c2MT: One or more of those pieces do not belong to you."); + return; + } + } + } + + //now we need to determine if at least 4 of the pieces axies match + %pos1[0] = %piece1.getEdge("1 1 -1"); + %pos1[1] = %piece1.getEdge("-1 1 -1"); + %pos1[2] = %piece1.getEdge("1 -1 -1"); + %pos1[3] = %piece1.getEdge("-1 -1 -1"); + %pos1[4] = %piece1.getEdge("1 1 1"); + %pos1[5] = %piece1.getEdge("-1 1 1"); + %pos1[6] = %piece1.getEdge("1 -1 1"); + %pos1[7] = %piece1.getEdge("-1 -1 1"); + + %pos2[0] = %piece2.getEdge("1 1 -1"); + %pos2[1] = %piece2.getEdge("-1 1 -1"); + %pos2[2] = %piece2.getEdge("1 -1 -1"); + %pos2[3] = %piece2.getEdge("-1 -1 -1"); + %pos2[4] = %piece2.getEdge("1 1 1"); + %pos2[5] = %piece2.getEdge("-1 1 1"); + %pos2[6] = %piece2.getEdge("1 -1 1"); + %pos2[7] = %piece2.getEdge("-1 -1 1"); + //then we compare them to see which ones match + %k = 0; + for (%i = 0; %i < 8; %i++) + { + for (%j = 0; %j < 8; %j++) + { + if ($ElecMod::MergeTool::Tolerance >= vectorDist(%pos1[%i], %pos2[%j])) + { + %k++; + } + } + } + //if less then 4 match, they can't be compatable (if more then 4 match... something odd is going on) + if (%k < 4) + { + if (%k == 0) + messageClient(%client, 'MsgClient', "\c2MT: None of the corners are shared on those objects. Cannot merge."); + else + messageClient(%client, 'MsgClient', "\c2MT: Only " @ %k @ " corners of the required 4 are shared."); + + return; + } + //if the check survived that, we continue... + return 1; +} + +//this function, after the pieces are confirmed, checks to see which of the 6 sides is in contact, refers to another +//function to find the alter side, determines distance between them to find a new "real" scale, and determines the +//new world box center for the object. Piece 1 is resized and moved, piece 2 is deconstructed. +function MTScaleShiftMerge(%piece1, %piece2) +{ + //find which axis is touching for a "this is the side we scale" discovery + //table: + //0: X + //1: -X + //2: Y + //3: -Y + //4: Z + //5: -Z + + %p1S[0] = %piece1.getEdge("1 0 0"); + %p1S[1] = %piece1.getEdge("-1 0 0"); + %p1S[2] = %piece1.getEdge("0 1 0"); + %p1S[3] = %piece1.getEdge("0 -1 0"); + %p1S[4] = %piece1.getEdge("0 0 1"); + %p1S[5] = %piece1.getEdge("0 0 -1"); + + %p2S[0] = %piece2.getEdge("1 0 0"); + %p2S[1] = %piece2.getEdge("-1 0 0"); + %p2S[2] = %piece2.getEdge("0 1 0"); + %p2S[3] = %piece2.getEdge("0 -1 0"); + %p2S[4] = %piece2.getEdge("0 0 1"); + %p2S[5] = %piece2.getEdge("0 0 -1"); + + for (%i = 0; %i < 6; %i++) + { + for (%j = 0; %j < 8; %j++) + { + if ($ElecMod::MergeTool::Tolerance >= vectorDist(%p1S[%i], %p2S[%j])) + { + %side1 = %i; + %side2 = %j; + } + } + } + //echo("Sides:" SPC %i SPC %j); + //at this point %side1/2 will contain one of the numbers in the table above + //we get the non-shared side at this point + %ops1 = MTFindOpSide(%side1); + %ops2 = MTFindOpSide(%side2); + + //this variable contains the new axis length that we are scaling on... + %newaxis = VectorDist(%p1S[%ops1], %p2S[%ops2]); + %currsize = %piece1.getRealSize(); + + if (%side1 == 0 || %side1 == 1) + %axis = "x"; + if (%side1 == 2 || %side1 == 3) + %axis = "y"; + if (%side1 == 4 || %side1 == 5) + %axis = "z"; + + //echo("Axis:" SPC %axis); + if (%axis $= "x") + %piece1.setRealSize(%newaxis SPC getWords(%currsize, 1, 2)); + if (%axis $= "y") + %piece1.setRealSize(getWord(%currsize, 0) SPC %newaxis SPC getWord(%currsize, 2)); + if (%axis $= "z") + %piece1.setRealSize(getWords(%currsize, 0, 1) SPC %newaxis); + if (%axis !$= "x" && %axis !$= "y" && %axis !$= "z") + { + error("MT: A scaling error has occured."); + return; + } + %newpos = VectorScale(VectorAdd(%p1S[%ops1], %p2S[%ops2]), 0.5); + %piece1.SetWorldBoxCenter(%newpos); + + %piece1.setCloaked(false); + %piece2.setCloaked(false); + + //%piece2.delete(); //deleting is bad + disassemble(0, %piece2.owner, %piece2); //disassemble is cleaner +} + +//this function does something very simple, it finds whether a number is even or odd, and then adds or subracts +//and returns the initial input with that modification. I can't imagine where else this could be useful. +function MTFindOpSide(%side) +{ + %evencheck = %side / 2; + if (%evencheck == mFloor(%evencheck)) + %even = 1; + else + %even = 0; + + if (%even) + return (%side + 1); + else + return (%side - 1); +} + +//simply clears a client variable... woohoo... +function MTClearClientSelection(%client) +{ + %client.mergePiece1 = ""; +} + + +//"weapon" datablocks and such +datablock ItemData(MergeTool) +{ + className = Weapon; + catagory = "Spawn Items"; + shapeFile = "weapon_sniper.dts"; + image = MergeToolImage; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 2; + pickUpName = "a merge tool"; + + computeCRC = true; + +}; + +datablock ShapeBaseImageData(MergeToolImage) +{ + className = WeaponImage; + shapeFile = "weapon_sniper.dts"; + item = MergeTool; + + usesEnergy = true; + minEnergy = 0; + + stateName[0] = "Activate"; + stateTransitionOnTimeout[0] = "ActivateReady"; + stateSound[0] = SniperRifleSwitchSound; + stateTimeoutValue[0] = 0.1; + stateSequence[0] = "Activate"; + + stateName[1] = "ActivateReady"; + stateTransitionOnLoaded[1] = "Ready"; + stateTransitionOnNoAmmo[1] = "NoAmmo"; + + stateName[2] = "Ready"; + stateTransitionOnNoAmmo[2] = "NoAmmo"; + stateTransitionOnTriggerDown[2] = "CheckWet"; + + stateName[3] = "Fire"; + stateTransitionOnTimeout[3] = "Reload"; + stateTimeoutValue[3] = 0.2; //reload timeout here + stateFire[3] = true; + stateAllowImageChange[3] = false; + stateSequence[3] = "Fire"; + stateScript[3] = "onFire"; + + stateName[4] = "Reload"; + stateTransitionOnTimeout[4] = "Ready"; + stateTimeoutValue[4] = 0.1; + stateAllowImageChange[4] = false; + + stateName[5] = "CheckWet"; + stateTransitionOnWet[5] = "Fire"; + stateTransitionOnNotWet[5] = "Fire"; + + stateName[6] = "NoAmmo"; + stateTransitionOnAmmo[6] = "Reload"; + stateTransitionOnTriggerDown[6] = "DryFire"; + stateSequence[6] = "NoAmmo"; + + stateName[7] = "DryFire"; + stateSound[7] = SniperRifleDryFireSound; + stateTimeoutValue[7] = 0.1; + stateTransitionOnTimeout[7] = "Ready"; +}; + //modified below for calling of the modes +function MergeToolImage::onFire(%data,%obj,%slot) +{ + serverPlay3D(chsingleshot, %obj.getTransform()); + %client = %obj.client; + +if (%obj.modifierMode==5){ + %client.scaler=getword($WeaponSetting["modifier4",%client.player.modifierMode2],0); + messageclient(%client, 'MsgClient', "\c2Modifier Tool [Scaler] set to" SPC %client.scaler); + return; + } + + %pos = %obj.getMuzzlePoint($WeaponSlot); + %vec = %obj.getMuzzleVector($WeaponSlot); + %targetpos = VectorAdd(%pos, VectorScale(%vec, 200)); + %piece = containerRaycast(%pos, %targetpos, $TypeMasks::StaticShapeObjectType | $TypeMasks::ForceFieldObjectType, %obj);//changed to $allobjmask so it can see ff's + %piece = getWord(%piece, 0); + %dataBlockName = %piece.getDataBlock().getName(); +if ( + %dataBlockName $= "StationInventory" || + %dataBlockName $= "GeneratorLarge" || + %dataBlockName $= "SolarPanel" || + %dataBlockName $= "SensorMediumPulse" || + %dataBlockName $= "SensorLargePulse" + ) +if (%piece.deployed != true) + return; + + if (!isObject(%piece)) + return; + + if (!%client.isAdmin) + { + if (%piece.owner != %client) + { + messageClient(%client, 'MsgClient', "\c2MT: That piece isn't yours."); + return; + } + } +///here the code for the other cheks +if (%obj.modifierMode==1){ + swaping(%piece,%obj,%obj.modifierMode2,0); + return; + } +else if (%obj.modifierMode==2){ + swaping(%piece,%obj,%obj.modifierMode2,1); + return; + } +else if (%obj.modifierMode==3){ + scaling(%piece,%client); + return; + } +else if (%obj.modifierMode==4){ + nudging(%piece,%client); + return; + } + if (!isObject(%client.mergePiece1)) + { + %client.mergePiece1 = %piece; + + %piece.setCloaked(true); + %piece.schedule(290, "setCloaked", false); + + %client.mergeschedule = schedule($ElecMod::MergeTool::Timeout * 1000, 0, "MTClearClientSelection", %client); + } + else + { + if (%piece != %client.mergePiece1) + { + MTMerge(%client, %client.mergePiece1, %piece); + MTClearClientSelection(%client); + } + else + { + messageClient(%client, 'MsgClient', "\c2MT: You cannot merge one piece into itself."); + return; + } + } +} + +//to electricutioner make shure you keep this in ur next vertion +//cos your merge tool has becomed the modifier tool +function MergeToolImage::onMount(%this,%obj,%slot) +{ + Parent::onMount(%this, %obj, %slot); +%obj.usingmodifier = true; +if (%obj.modifierMode2 $= "") + %obj.modifierMode2 = 0; +if (%obj.modifierMode $= "") + %obj.modifierMode = 0; + %obj.client.setWeaponsHudActive("sniperrifle"); + %line = getWords($WeaponSettings2["modifier",%this.modifierMode],1,10); + %obj.mountImage(MergeToolImage, 0); +} +function MergeToolImage::onUnmount(%data, %obj, %slot) { +%obj.usingmodifier = false; +WeaponImage::onUnmount(%data, %obj, %slot); +} + +//NUDGING + +function nudging(%obj,%client){ +%obj.setCloaked(true); +%obj.schedule(150, "setCloaked", false); + +%dataBlock = %obj.getDataBlock(); +%name = %dataBlock.getname(); +%className = %dataBlock.className; +if (%obj.squaresize !$="") + return; +%Transform = %obj.getTransform(); +%pos = posFromTransform(%Transform); +%dir = %obj.getForwardVector(); + +if (%client.player.modifierMode2==2) + %axis=realvec(%obj,"1 0 0");//x +if (%client.player.modifierMode2==3) + %axis=realvec(%obj,"-1 0 0");//-x + +if (%client.player.modifierMode2==4) + %axis=realvec(%obj,"0 1 0");//y +if (%client.player.modifierMode2==5) + %axis=realvec(%obj,"0 -1 0");//-y + +if (%client.player.modifierMode2==6) + %axis=realvec(%obj,"0 0 1");//z +if (%client.player.modifierMode2==7) + %axis=realvec(%obj,"0 0 -1");//-z + if (%client.scaler$="")//if the scaler dosnt exist + %client.scaler=0.1; //default 0.1 +%NewPosition=vectorAdd(%pos,vectorScale(%axis,%client.scaler)); +if (%client.player.modifierMode2==0) //up + %NewPosition=VectorAdd(%pos,VectorScale("0 0 1",%client.scaler)); +if (%client.player.modifierMode2==1) //down + %NewPosition=VectorAdd(%pos,VectorScale("0 0 -1",%client.scaler)); +if (%obj.originalpos $="") + %obj.originalpos=%NewPosition; +%dist=VectorDist(%NewPosition,%obj.originalpos); +if (%dist>8){ + messageclient(%client, 'MsgClient', "\c2Piece is too far from original position."); + return; + } +if (%obj.isdoor==1){//only scale door that are fully closed and not moving + if (%obj.canmove == false){ + messageclient(%client, 'MsgClient', "\c2You cannot move a door that is already moving."); + return; + } + if(%obj.state !$="closed" && %obj.state !$=""){ + messageclient(%client, 'MsgClient', "\c2You can only move fully closed doors."); + return; + } + } +%obj.setTransform(%NewPosition); +//below is to make shure that all atatch parts will folow the main piece +checkAfterRot(%obj); + +} + +//SCALING + +function scaling(%obj,%client){ +%dataBlock = %obj.getDataBlock(); +%name = %dataBlock.getname(); +%className = %dataBlock.className; +if (%obj.squaresize !$="") + return; +%Transform = %obj.getTransform(); +if (%client.player.modifierMode2==0 || %client.player.modifierMode2==4)//sets + %axis="1 1 1"; //the +if (%client.player.modifierMode2==1 || %client.player.modifierMode2==5)//right + %axis="1 0 0"; //vector +if (%client.player.modifierMode2==2 || %client.player.modifierMode2==6)//for + %axis="0 1 0"; //scaling +if (%client.player.modifierMode2==3 || %client.player.modifierMode2==7)// + %axis="0 0 1"; // +if (%client.player.modifierMode2>3)//inverts it + %axis=VectorScale(%axis,-1); //if its on a -scale +if (%client.scaler$="")//if the scaler dosnt exist + %client.scaler=0.1; //default 0.1 +%multiplier=VectorScale(%axis,%client.scaler);//gets the multiplier +if (%obj.isdoor==1){//only scale door that are fully closed and not moving + if (%obj.canmove == false){ + messageclient(%client, 'MsgClient', "\c2You cannot scale a door while it is moving."); + return; + } + if(%obj.state !$="closed" && %obj.state !$=""){ + messageclient(%client, 'MsgClient', "\c2You can only scale doors while fully closed."); + return; + } + } +//so spines scale corectly +if (%classname $= "spine" || %classname $= "mspine" || %classname $= "spine2" || %classname $= "floor" || %classname $= "wall" || %classname $= "wwall" || %classname $= "floor" || %classname $= "door") { + %multiplier=VectorScale(%multiplier,"0.125 0.166666 1"); + %size=Vectoradd(%obj.getScale(),%multiplier); + if (getword(%size,0)<0.001 || getword(%size,1)<0.001 || getword(%size,2)<0.001){ //just so + messageclient(%client, 'MsgClient', "\c2Piece is too small."); //it dont go + return; //to small + } + if (getword(%size,0)>100 || getword(%size,1)>100 || getword(%size,2)>100){ //just so + messageclient(%client, 'MsgClient', "\c2Piece is too big."); //it dont go + return; //to big + } + %obj.setScale(%size); + return; + } +//so if you hit a target its the decorations that scales +if (%name $="DeployedLTarget"){ + %size=vectoradd(%obj.lMain.getScale(),%multiplier); + if (getword(%size,0)<0.001 || getword(%size,1)<0.001 || getword(%size,2)<0.001){ + messageclient(%client, 'MsgClient', "\c2Piece is too small."); + return; + } + if (getword(%size,0)>100 || getword(%size,1)>100 || getword(%size,2)>100){ //just so + messageclient(%client, 'MsgClient', "\c2Piece is too big."); //it dont go + return; //to big + } + %obj.lMain.setScale(%size); + adjustLMain(%obj); + return; + } +//so both the logo and the projector scales at once +if (%name $="DeployedLogoProjector"){ + %size=vectoradd(%obj.getScale(),%multiplier); + if (getword(%size,0)<0.01 || getword(%size,1)<0.01 || getword(%size,2)<0.01){//smaller then that + messageclient(%client, 'MsgClient', "\c2Piece is too small."); //and its to small to deconstruct + return; + } + if (getword(%size,0)>100 || getword(%size,1)>100 || getword(%size,2)>100){ //just so + messageclient(%client, 'MsgClient', "\c2Piece is too big."); //it dont go + return; //to big + } + %obj.setScale(%size); + if (%obj.holo !=""){ + if (isobject(%obj.holo)){ + %obj.holo.setScale(%size); + adjustHolo(%obj); + } + } + return; + } +%size=vectoradd(%obj.getScale(),%multiplier); +if (getword(%size,0)<0.001 || getword(%size,1)<0.001 || getword(%size,2)<0.001){ + messageclient(%client, 'MsgClient', "\c2Piece is too small."); + return; + } + if (getword(%size,0)>100 || getword(%size,1)>100 || getword(%size,2)>100){ //just so + messageclient(%client, 'MsgClient', "\c2Piece is too big."); //it dont go + return; //to big + } +%obj.setScale(%size); +} + +//SWAPPING + +function swaping(%hitobj,%plyr,%mode,%mode2){ +%sender=%plyr.client; +if ( %hitobj.ownerGUID != %sender.guid){ + if (!%sender.isadmin && !%sender.issuperadmin){ + if (%hitobj.ownerGUID !$=""){ + messageclient(%sender, 'MsgClient', '\c2You do not own this.'); + return; + } + } + } +if (%hitobj.squaresize !$="") + return; +%classname= %hitobj.getDataBlock().classname; +%objscale = %hitobj.scale; +%grounded = %hitobj.grounded; +%pwrfreq = %hitobj.powerFreq; +%Transform = %hitobj.getTransform(); + +////////////// +//forcefeild// +////////////// +if (%classname$="forcefield" && %mode2==1){ + %db="DeployedForceField"@%mode; + %deplObj = new ("ForceFieldBare")() { + dataBlock = %db; + scale = %objscale; + }; + %deplObj.setTransform(%Transform); + if (%hitobj.noSlow == true){ + %deplObj.noSlow = true; + %deplObj.pzone.delete(); + %deplObj.pzone = ""; + } + if (%hitobj.pzone !$= "") + %hitobj.pzone.delete(); + %hitobj.delete(); + + // misc info + addDSurface(%item.surface,%deplObj); + + // [[Settings]]: + + %deplObj.grounded = %grounded; + %deplObj.needsFit = 1; + + // [[Normal Stuff]]: + + // set team, owner, and handle + %deplObj.team = %plyr.client.team; + %deplObj.setOwner(%plyr); + + // set power frequency + %deplObj.powerFreq = %pwrfreq; + + // set the sensor group if it needs one + if (%deplObj.getTarget() != -1) + setTargetSensorGroup(%deplObj.getTarget(), %plyr.client.team); + + // place the deployable in the MissionCleanup/Deployables group (AI reasons) + addToDeployGroup(%deplObj); + + //let the AI know as well... + AIDeployObject(%plyr.client, %deplObj); + + // increment the team count for this deployed object + $TeamDeployedCount[%plyr.team, %item.item]++; + + // Power object + checkPowerObject(%deplObj); + + return %deplObj; + } +///////////%objscale = %hitobj.scale; +//pads //%oldpos = %hitobj.position; +///////////%oldrot = %hitobj.rotation; +else if (%mode2==0 && ((%classname $= "decoration" && %hitobj.getDataBlock().getname() $="DeployedDecoration6") || %classname $= "crate" || %classname $= "floor" || %classname $= "spine" || %classname $= "mspine" || %classname $= "wall" || %classname $= "wwall" || %classname $= "Wspine" || %classname $= "Sspine" || %classname $= "floor" || %classname $= "door")) + { +%hitobj.setCloaked(true); +%hitobj.schedule(290, "setCloaked", false); +if (%hitobj.isdoor == 1 || %hitobj.getdatablock().getname() $="DeployedTdoor"){ + if (%hitobj.canmove == false) //if it cant move + return; + if (%hitobj.state !$="closed" && %hitobj.state !$="") + return; + } +if (%hitobj.isobjective > 0) + return; + + %db = getword($WeaponSetting["modifier1",%mode],0); + %count = $WeaponSettings["modifier1"]; //counts + if (%hitobj.getdatablock().getname() $="DeployedFloor") + %datablock="DeployedwWall"; + else if (%hitobj.getdatablock().getname() $="DeployedMSpinering") + %datablock="DeployedMSpine"; + else if (%hitobj.getdatablock().getname() $="DeployedTdoor"){ + %datablock="DeployedMSpine"; + } + else + %datablock=%hitobj.getdatablock().getname(); + + + %team = %hitobj.team; + %owner = %hitobj.owner; + if (%hitobj.ownerGUID>0) + %ownerGUID = %hitobj.ownerGUID; + else + %ownerGUID = ""; + + if (%hitobj.isdoor == 1 || %hitobj.getdatablock().getname() $="DeployedTdoor"){ + %issliding = %hitobj.issliding; + %state = %hitobj.state; + %canmove = %hitobj.canmove; + %closedscale = %hitobj.closedscale; + %openedscale = %hitobj.openedscale; + %oldscale = %hitobj.oldscale; + %moving = %hitobj.moving; + %toggletype = %hitobj.toggletype; + %powercontrol = %hitobj.powercontrol; + %Collision = %hitobj.Collision; + %lv = %hitobj.lv; + } + + %scale = %hitobj.GetRealSize(); + + %deplObj = new ("StaticShape")() { + dataBlock = %db; + }; + %deplObj.SetRealSize(%scale); + %deplObj.setTransform(%Transform); +//////////////////////////Apply settings////////////////////////////// + + // misc info + addDSurface(%item.surface,%deplObj); + + // [[Settings]]: + + %deplObj.grounded = %grounded; + %deplObj.needsFit = 1; + + // set team, owner, and handle + %deplObj.team = %team; + %deplObj.Ownerguid=%ownerGUID; + %deplObj.Owner=%owner; + + // set power frequency + %deplObj.powerFreq = %pwrfreq; + %deplObj.OriginalPos = %hitobj.OriginalPos; + // set the sensor group if it needs one + if (%deplObj.getTarget() != -1) + setTargetSensorGroup(%deplObj.getTarget(), %plyr.client.team); + + // place the deployable in the MissionCleanup/Deployables group (AI reasons) + addToDeployGroup(%deplObj); + + //let the AI know as well... + AIDeployObject(%plyr.client, %deplObj); + + // increment the team count for this deployed object + $TeamDeployedCount[%plyr.team, %item.item]++; + + %deplObj.deploy(); + + // Power object + checkPowerObject(%deplObj); + + if (%hitobj.isdoor == 1 || %hitobj.getdatablock().getname() $="DeployedTdoor"){ + %deplObj.closedscale = %deplObj.getScale(); + %deplObj.openedscale = getwords(%deplObj.getScale(),0,1) SPC 0.1; + %deplObj.isdoor = 1; + %deplObj.state = %state ; + %deplObj.canmove = %canmove ; + %deplObj.moving = %moving ; + %deplObj.toggletype = %toggletype ; + %deplObj.powercontrol = %powercontrol; + %deplObj.Collision = %Collision ; + %deplObj.lv = %lv ; + } +%hitobj.delete(); + return %deplObj; + } +} diff --git a/scripts/weapons/nerfBallLauncher.cs b/scripts/weapons/nerfBallLauncher.cs new file mode 100644 index 0000000..ff7d8ff --- /dev/null +++ b/scripts/weapons/nerfBallLauncher.cs @@ -0,0 +1,288 @@ +//-------------------------------------------------------------------------- +// Nerf Ball Launcher +// ------------------------------------------------------------------------ + +//-------------------------------------------------------------------------- +// Nerf Ball Launcher Ball +// ------------------------------------------------------------------------ + +datablock AudioProfile(NerfBallBurnSound) +{ + filename = "fx/armor/bubbletrail.wav"; + description = ProjectileLooping3d; + preload = true; +}; + +datablock AudioProfile(NerfBallExplosionSound) +{ + filename = "fx/weapons/cg_water2.wav"; + description = AudioClosest3d; + preload = true; +}; + +//-------------------------------------------------------------------------- +// Particle effects +//-------------------------------------- +datablock ParticleData(NerfBallParticle) +{ + dragCoeffiecient = 0.0; + gravityCoefficient = 0.15; + inheritedVelFactor = 0.5; + + lifetimeMS = 3000; + lifetimeVarianceMS = 200; + + spinRandomMin = -200.0; + spinRandomMax = 200.0; + + textureName = "special/bubbles"; + + colors[0] = "0.0 0.5 1.0 0.3"; + colors[1] = "0.0 0.4 1.0 0.2"; + colors[2] = "0.0 0.3 1.0 0.1"; + + sizes[0] = 0.6; + sizes[1] = 0.3; + sizes[2] = 0.1; + + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; + +}; + +datablock ParticleEmitterData(NerfBallEmitter) +{ + lifetimeMS = 0; // No limit + + ejectionPeriodMS = 10; + periodVarianceMS = 0; + + ejectionVelocity = 1.0; + velocityVariance = 0.5; + + thetaMin = 0.0; + thetaMax = 90.0; + + orientParticles = false; + orientOnVelocity = false; + + particles = "NerfBallParticle"; +}; + +datablock ParticleData(NerfBallExplosionParticle) +{ + dragCoeffiecient = 0.0; + gravityCoefficient = 0.5; + inheritedVelFactor = 0.5; + + lifetimeMS = 2000; + lifetimeVarianceMS = 200; + + spinRandomMin = -200.0; + spinRandomMax = 200.0; + + textureName = "special/bubbles"; + + colors[0] = "0.0 0.5 1.0 0.3"; + colors[1] = "0.0 0.4 1.0 0.2"; + colors[2] = "0.0 0.3 1.0 0.1"; + + sizes[0] = 0.6; + sizes[1] = 0.3; + sizes[2] = 0.1; + + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; + +}; + +datablock ParticleEmitterData(NerfBallExplosionEmitter) +{ + lifetimeMS = 200; + + ejectionPeriodMS = 1; + periodVarianceMS = 0; + + ejectionVelocity = 3.0; + velocityVariance = 0.5; + + thetaMin = 0.0; + thetaMax = 90.0; + + orientParticles = false; + orientOnVelocity = false; + + particles = "NerfBallExplosionParticle"; +}; + +//-------------------------------------------------------------------------- +// Explosion - Nerf Ball Launcher Ball +//-------------------------------------- +datablock ExplosionData(NerfBallExplosion) +{ + emitter[0] = NerfBallExplosionEmitter; + soundProfile = NerfBallExplosionSound; +}; + +//-------------------------------------------------------------------------- +// Projectile - Nerf Ball Launcher Ball +//-------------------------------------- +datablock GrenadeProjectileData(NerfBall) +{ + projectileShapeName = "grenade_projectile.dts"; + emitterDelay = -1; + directDamage = 0; + directDamageType = $DamageType::Default; + radiusDamageType = $DamageType::Default; + hasDamageRadius = false; + indirectDamage = 0; + damageRadius = 3.0; // used in onExplode() + kickBackStrength = 0; + useLensFlare = false; + + sound = NerfBallBurnSound; + explosion = NerfBallExplosion; + velInheritFactor = 0.5; + + texture[0] = "special/bubbles"; + + baseEmitter = NerfBallEmitter; + + grenadeElasticity = 0.35; + grenadeFriction = 0.1; + armingDelayMS = 1500; + muzzleVelocity = 60; + drag = 0.1; + gravityMod = 3.0; +}; + +//-------------------------------------- +// Nerf Ball Launcher +//-------------------------------------- + +datablock AudioProfile(NerfBallLauncherFireSound) +{ + filename = "fx/vehicles/crash_ground_vehicle.wav"; + description = AudioDefault3d; + preload = true; + effect = GrenadeFireEffect; +}; + +datablock AudioProfile(NerfBallLauncherReloadSound) +{ + filename = "heavy_RF_uw.wav"; + description = AudioClosest3d; + preload = true; + effect = GrenadeReloadEffect; +}; + +//-------------------------------------------------------------------------- +// Ammo +//-------------------------------------- + +datablock ItemData(NerfBallLauncherAmmo) +{ + className = Ammo; + catagory = "Ammo"; + shapeFile = "ammo_grenade.dts"; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 2; + pickUpName = "some nerf ball launcher ammo"; + computeCRC = true; + emap = true; +}; + +//-------------------------------------------------------------------------- +// Weapon +//-------------------------------------- +datablock ItemData(NerfBallLauncher) +{ + className = Weapon; + catagory = "Spawn Items"; + shapeFile = "weapon_grenade_launcher.dts"; + image = NerfBallLauncherImage; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 2; + pickUpName = "a nerf ball launcher"; + computeCRC = true; + +}; + +datablock ShapeBaseImageData(NerfBallLauncherImage) +{ + className = WeaponImage; + shapeFile = "weapon_grenade_launcher.dts"; + item = NerfBallLauncher; + ammo = NerfBallLauncherAmmo; + offset = "0 0 0"; + emap = true; + + projectile = NerfBall; + projectileType = GrenadeProjectile; + + projectileSpread = 30.0 / 1000.0; + + stateName[0] = "Activate"; + stateTransitionOnTimeout[0] = "ActivateReady"; + stateTimeoutValue[0] = 0.5; + stateSequence[0] = "Activate"; + stateSound[0] = GrenadeSwitchSound; + + stateName[1] = "ActivateReady"; + stateTransitionOnLoaded[1] = "Ready"; + stateTransitionOnNoAmmo[1] = "NoAmmo"; + + stateName[2] = "Ready"; + stateTransitionOnNoAmmo[2] = "NoAmmo"; + stateTransitionOnTriggerDown[2] = "Fire"; + + stateName[3] = "Fire"; + stateTransitionOnTimeout[3] = "Reload"; + stateTimeoutValue[3] = 0.05; + stateFire[3] = true; + stateRecoil[3] = LightRecoil; + stateAllowImageChange[3] = false; + stateSequence[3] = "Fire"; + stateScript[3] = "onFire"; + stateSound[3] = NerfBallLauncherFireSound; + + stateName[4] = "Reload"; + stateTransitionOnNoAmmo[4] = "NoAmmo"; + stateTransitionOnTimeout[4] = "Ready"; + stateTimeoutValue[4] = 0.1; + stateAllowImageChange[4] = false; + stateSequence[4] = "Reload"; + stateSound[4] = NerfBallLauncherReloadSound; + + stateName[5] = "NoAmmo"; + stateTransitionOnAmmo[5] = "Reload"; + stateSequence[5] = "NoAmmo"; + stateTransitionOnTriggerDown[5] = "DryFire"; + + stateName[6] = "DryFire"; + stateSound[6] = GrenadeDryFireSound; + stateTimeoutValue[6] = 1.5; + stateTransitionOnTimeout[6] = "NoAmmo"; +}; + +function NerfBall::onExplode(%data,%projectile,%pos,%mod) { + InitContainerRadiusSearch(%pos, %data.damageRadius, $TypeMasks::PlayerObjectType); + while ((%targetObject = containerSearchNext()) != 0) { + if (isObject(%targetObject)) { + if (%targetObject.getClassName() $= "Player") + applyNerf(%targetObject,%projectile.sourceObject,%pos); + } + } +} + +// Bot fun! +function NerfBallLauncherImage::onFire(%data,%obj,%slot) { + %p = Parent::onFire(%data, %obj, %slot); + AIGrenadeThrown(%p); +} diff --git a/scripts/weapons/nerfGun.cs b/scripts/weapons/nerfGun.cs new file mode 100644 index 0000000..f3f5f71 --- /dev/null +++ b/scripts/weapons/nerfGun.cs @@ -0,0 +1,250 @@ +//-------------------------------------- +// Nerf Gun +//-------------------------------------- + +//-------------------------------------------------------------------------- +// Sounds +//-------------------------------------- +datablock AudioProfile(NerfGunFireSound) +{ + filename = "fx/armor/heavy_LF_uw.wav"; + description = AudioDefault3d; + preload = true; + effect = BlasterFireEffect; +}; + +datablock AudioProfile(NerfGunDryFireSound) +{ + filename = "fx/weapons/chaingun_dryfire.wav"; + description = AudioClose3d; + preload = true; +}; + +datablock AudioProfile(NerfBoltProjectileSound) +{ + filename = "fx/weapons/ELF_hit.WAV"; + description = ProjectileLooping3d; + preload = true; +}; + +datablock AudioProfile(NerfBoltExpSound) +{ + filename = "fx/armor/heavy_LF_metal.wav"; + description = AudioClosest3d; + preload = true; +}; + +//-------------------------------------------------------------------------- +// Explosion +//-------------------------------------- +datablock ParticleData(NerfBoltExplosionParticle1) +{ + dragCoefficient = 2; + gravityCoefficient = 0.0; + inheritedVelFactor = 0.2; + constantAcceleration = -0.0; + lifetimeMS = 600; + lifetimeVarianceMS = 000; + textureName = "special/crescent4"; + colors[0] = "0.1 1.0 0.1 1.0"; + colors[1] = "0.1 1.0 0.1 1.0"; + colors[2] = "0.0 0.0 0.0 0.0"; + sizes[0] = 0.25; + sizes[1] = 0.5; + sizes[2] = 1.0; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; +}; + +datablock ParticleEmitterData(NerfBoltExplosionEmitter) +{ + ejectionPeriodMS = 7; + periodVarianceMS = 0; + ejectionVelocity = 2; + velocityVariance = 1.5; + ejectionOffset = 0.0; + thetaMin = 70; + thetaMax = 80; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + orientParticles = true; + lifetimeMS = 200; + particles = "NerfBoltExplosionParticle1"; +}; + +datablock ParticleData(NerfBoltExplosionParticle2) +{ + dragCoefficient = 2; + gravityCoefficient = 0.0; + inheritedVelFactor = 0.2; + constantAcceleration = -0.0; + lifetimeMS = 600; + lifetimeVarianceMS = 000; + textureName = "special/blasterHit"; + colors[0] = "0.1 1.0 0.1 1.0"; + colors[1] = "0.1 0.5 0.1 0.5"; + colors[2] = "0.0 0.0 0.0 0.0"; + sizes[0] = 0.3; + sizes[1] = 0.90; + sizes[2] = 1.50; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; +}; + +datablock ParticleEmitterData(NerfBoltExplosionEmitter2) +{ + ejectionPeriodMS = 30; + periodVarianceMS = 0; + ejectionVelocity = 1; + velocityVariance = 0.0; + ejectionOffset = 0.0; + thetaMin = 0; + thetaMax = 80; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + orientParticles = false; + lifetimeMS = 200; + particles = "NerfBoltExplosionParticle2"; +}; + +datablock ExplosionData(NerfBoltExplosion) +{ + soundProfile = NerfBoltExpSound; + emitter[0] = NerfBoltExplosionEmitter; + emitter[1] = NerfBoltExplosionEmitter2; +}; + + +//-------------------------------------------------------------------------- +// Projectile +//-------------------------------------- + +datablock LinearFlareProjectileData(NerfBolt) +{ + emitterDelay = -1; + directDamage = 0; + directDamageType = $DamageType::Default; + kickBackStrength = 0.0; + bubbleEmitTime = 1.0; + + sound = NerfBoltProjectileSound; + velInheritFactor = 0.5; + + explosion = "NerfBoltExplosion"; + splash = BlasterSplash; + + grenadeElasticity = 0.998; + grenadeFriction = 0.0; + armingDelayMS = 500; + + muzzleVelocity = 100.0; + + drag = 0.05; + + gravityMod = 0.0; + + dryVelocity = 100.0; + wetVelocity = 80.0; + + reflectOnWaterImpactAngle = 0.0; + explodeOnWaterImpact = false; + deflectionOnWaterImpact = 0.0; + fizzleUnderwaterMS = 3000; + + lifetimeMS = 3000; + + scale = "0.1 0.1 0.1"; + numFlares = 8; + flareColor = "0.1 1 0.1"; + flareModTexture = "flaremod"; + flareBaseTexture = "special/lightFalloffMono"; +}; + + +//-------------------------------------------------------------------------- +// Weapon +//-------------------------------------- +datablock ShapeBaseImageData(NerfGunImage) +{ + className = WeaponImage; + shapeFile = "weapon_energy.dts"; + item = NerfGun; + + projectile = NerfBolt; + projectileType = LinearFlareProjectile; + + usesEnergy = true; + fireEnergy = 4; + minEnergy = 4; + + stateName[0] = "Activate"; + stateTransitionOnTimeout[0] = "ActivateReady"; + stateTimeoutValue[0] = 0.5; + stateSequence[0] = "Activate"; + stateSound[0] = BlasterSwitchSound; + + stateName[1] = "ActivateReady"; + stateTransitionOnLoaded[1] = "Ready"; + stateTransitionOnNoAmmo[1] = "NoAmmo"; + + stateName[2] = "Ready"; + stateTransitionOnNoAmmo[2] = "NoAmmo"; + stateTransitionOnTriggerDown[2] = "Fire"; + + stateName[3] = "Fire"; + stateTransitionOnTimeout[3] = "Reload"; + stateTimeoutValue[3] = 0.3; + stateFire[3] = true; + stateRecoil[3] = NoRecoil; + stateAllowImageChange[3] = false; + stateSequence[3] = "Fire"; + stateSound[3] = NerfGunFireSound; + stateScript[3] = "onFire"; + + stateName[4] = "Reload"; + stateTransitionOnNoAmmo[4] = "NoAmmo"; + stateTransitionOnTimeout[4] = "Ready"; + stateAllowImageChange[4] = false; + stateSequence[4] = "Reload"; + + stateName[5] = "NoAmmo"; + stateTransitionOnAmmo[5] = "Reload"; + stateSequence[5] = "NoAmmo"; + stateTransitionOnTriggerDown[5] = "DryFire"; + + stateName[6] = "DryFire"; + stateTimeoutValue[6] = 0.3; + stateSound[6] = NerfGunDryFireSound; + stateTransitionOnTimeout[6] = "Ready"; +}; + +datablock ItemData(NerfGun) +{ + className = Weapon; + catagory = "Spawn Items"; + shapeFile = "weapon_energy.dts"; + image = NerfGunImage; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 2; + pickUpName = "a nerf gun"; +}; + +function NerfBolt::onCollision(%data,%projectile,%targetObject,%modifier,%position,%normal) { + if (isObject(%targetObject)) { + if (%targetObject.getClassName() $= "Player") + applyNerf(%targetObject,%projectile.sourceObject,%position); + } + Parent::onCollision(%data, %projectile, %targetObject, %modifier, %position, %normal); +} + +// Bot fun! +function NerfGunImage::onFire(%data,%obj,%slot) { + %p = Parent::onFire(%data, %obj, %slot); + AIGrenadeThrown(%p); +} diff --git a/scripts/weapons/superChaingun.cs b/scripts/weapons/superChaingun.cs new file mode 100644 index 0000000..59a9492 --- /dev/null +++ b/scripts/weapons/superChaingun.cs @@ -0,0 +1,259 @@ +//-------------------------------------- +// SuperChaingun +//-------------------------------------- + +//-------------------------------------------------------------------------- +// Projectile +//-------------------------------------- + +datablock TracerProjectileData(SuperChaingunBullet) +{ + doDynamicClientHits = true; + + directDamage =0.0825 * 4; + directDamageType = $DamageType::SuperChaingun; + explosion = ChaingunExplosion; + splash = ChaingunSplash; + + hasDamageRadius = true; + indirectDamage = 0.45 * 400; + damageRadius = 4.0 * 2; + radiusDamageType = $DamageType::SuperChaingun; + + kickBackStrength = 1750; + sound = ChaingunProjectile; + + dryVelocity = 425.0; + wetVelocity = 100.0; + velInheritFactor = 1.0; + fizzleTimeMS = 3000; + lifetimeMS = 3000; + explodeOnDeath = false; + reflectOnWaterImpactAngle = 0.0; + explodeOnWaterImpact = false; + deflectionOnWaterImpact = 0.0; + fizzleUnderwaterMS = 3000; + + tracerLength = 15.0; + tracerAlpha = false; + tracerMinPixels = 6; + tracerColor = 211.0/255.0 @ " " @ 215.0/255.0 @ " " @ 120.0/255.0 @ " 0.75"; + tracerTex[0] = "special/tracer00"; + tracerTex[1] = "special/tracercross"; + tracerWidth = 0.10; + crossSize = 0.20; + crossViewAng = 0.990; + renderCross = true; + + decalData[0] = ChaingunDecal1; + decalData[1] = ChaingunDecal2; + decalData[2] = ChaingunDecal3; + decalData[3] = ChaingunDecal4; + decalData[4] = ChaingunDecal5; + decalData[5] = ChaingunDecal6; + + hasLight = true; + lightRadius = 5.0; + lightColor = "0.5 0.5 0.175"; +}; + +//-------------------------------------------------------------------------- +// Ammo +//-------------------------------------- + +datablock ItemData(SuperChaingunAmmo) +{ + className = Ammo; + catagory = "Ammo"; + shapeFile = "ammo_chaingun.dts"; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 2; + pickUpName = "some super chaingun ammo"; + + computeCRC = true; + +}; + +//-------------------------------------------------------------------------- +// Weapon +//-------------------------------------- +datablock ShapeBaseImageData(SuperChaingunImage) +{ + className = WeaponImage; + shapeFile = "weapon_chaingun.dts"; + item = SuperChaingun; + ammo = SuperChaingunAmmo; + + projectile = SuperChaingunBullet; + projectileType = TracerProjectile; + + emap = true; + + casing = ShellDebris; + shellExitDir = "0.3 0.5 1.0"; + shellExitOffset = "0.15 -0.56 -0.1"; + shellExitVariance = 15.0; + shellVelocity = 4.0; + + projectileSpread = 2.0 / 1000.0; + + //-------------------------------------- + stateName[0] = "Activate"; + stateSequence[0] = "Activate"; + stateSound[0] = ChaingunSwitchSound; + stateAllowImageChange[0] = false; + // + stateTimeoutValue[0] = 0.5; + stateTransitionOnTimeout[0] = "Ready"; + stateTransitionOnNoAmmo[0] = "NoAmmo"; + + //-------------------------------------- + stateName[1] = "Ready"; + stateSpinThread[1] = Stop; + // + stateTransitionOnTriggerDown[1] = "Spinup"; + stateTransitionOnNoAmmo[1] = "NoAmmo"; + + //-------------------------------------- + stateName[2] = "NoAmmo"; + stateTransitionOnAmmo[2] = "Ready"; + stateSpinThread[2] = Stop; + stateTransitionOnTriggerDown[2] = "DryFire"; + + //-------------------------------------- + stateName[3] = "Spinup"; + stateSpinThread[3] = SpinUp; + stateSound[3] = ChaingunSpinupSound; + // + stateTimeoutValue[3] = 0.0; + stateWaitForTimeout[3] = false; + stateTransitionOnTimeout[3] = "Fire"; + stateTransitionOnTriggerUp[3] = "Spindown"; + + //-------------------------------------- + stateName[4] = "Fire"; + stateSequence[4] = "Fire"; + stateSequenceRandomFlash[4] = true; + stateSpinThread[4] = FullSpeed; + stateSound[4] = ChaingunFireSound; + //stateRecoil[4] = LightRecoil; + stateAllowImageChange[4] = false; + stateScript[4] = "onFire"; + stateFire[4] = true; + stateEjectShell[4] = true; + // + stateTimeoutValue[4] = 0.01; + stateTransitionOnTimeout[4] = "Fire"; + stateTransitionOnTriggerUp[4] = "Spindown"; + stateTransitionOnNoAmmo[4] = "EmptySpindown"; + + //-------------------------------------- + stateName[5] = "Spindown"; + stateSound[5] = ChaingunSpinDownSound; + stateSpinThread[5] = SpinDown; + // + stateTimeoutValue[5] = 0.0; + stateWaitForTimeout[5] = true; + stateTransitionOnTimeout[5] = "Ready"; + stateTransitionOnTriggerDown[5] = "Spinup"; + + //-------------------------------------- + stateName[6] = "EmptySpindown"; + stateSound[6] = ChaingunSpinDownSound; + stateSpinThread[6] = SpinDown; + // + stateTimeoutValue[6] = 0.5; + stateTransitionOnTimeout[6] = "NoAmmo"; + + //-------------------------------------- + stateName[7] = "DryFire"; + stateSound[7] = ChaingunDryFireSound; + stateTimeoutValue[7] = 0.5; + stateTransitionOnTimeout[7] = "NoAmmo"; +}; + +datablock ItemData(SuperChaingun) +{ + className = Weapon; + catagory = "Spawn Items"; + shapeFile = "weapon_chaingun.dts"; + image = SuperChaingunImage; + mass = 1; + elasticity = 0.2; + friction = 0.6; + pickupRadius = 2; + pickUpName = "a super chaingun"; + + computeCRC = true; + emap = true; +}; + +function SuperChaingunImage::onFire(%data,%obj,%slot) { + if (%obj.superChaingunMode == 1) { + %pos = %obj.getMuzzlePoint(%slot); + %vec = %obj.getMuzzleVector(%slot); + %res = containerRayCast(%pos,vectorAdd(%pos,vectorScale(%vec,2000)), $TypeMasks::PlayerObjectType | $TypeMasks::TerrainObjectType | $TypeMasks::InteriorObjectType | $TypeMasks::StaticObjectType,%obj); + if (%res) + %hitLoc = getWords(%res,1,3); + else + %hitLoc = vectorAdd(%pos,vectorScale(%vec,2000)); + %p = discharge(%pos,%vec); + %p.setEnergyPercentage(1); + createLifeLight(%hitLoc,1,1000); + addToShock(%p); + %p.schedule(1000,"delete"); + zap(0,25,%hitLoc); + %obj.decInventory(%data.ammo,1); + } + else if (%obj.superChaingunMode > 1) + { + if (!(%obj.lasteffectpulse+2000 < getSimTime())) + return; + %obj.lasteffectpulse = GetSimTime(); + %pos = %obj.getMuzzlePoint(%slot); + %vec = %obj.getMuzzleVector(%slot); + %res = containerRayCast(%pos,vectorAdd(%pos,vectorScale(%vec,2000)), $TypeMasks::PlayerObjectType | $TypeMasks::TerrainObjectType | $TypeMasks::InteriorObjectType | $TypeMasks::StaticObjectType| $TypeMasks::ForceFieldObjectType ,%obj); + if (%res) + Aidpulse(getWords(%res,1,3),%obj.client,%obj.superChaingunMode-2); + + } + else + //for (%i = 0; %i < 1; %i++) + //{ + Parent::onFire(%data, %obj, %slot); + //} +} + +function SuperChaingunImage::onMount(%this,%obj,%slot) { + %obj.usingSuperChaingun = true; + if (!%obj.superChaingunMode) + %obj.superChaingunMode = 0; + if (!%obj.superChaingunMode2) + %obj.superChaingunMode2 = 0; + displaySCGStatus(%obj); + WeaponImage::onMount(%this,%obj,%slot); +} + +function SuperChaingunImage::onUnmount(%data, %obj, %slot) { + %obj.usingSuperChaingun = false; + WeaponImage::onUnmount(%data, %obj, %slot); +} + +function displaySCGStatus(%obj) { + if (%obj.superChaingunMode == 1) + bottomPrint(%obj.client,">>>Super Chain Gun<<<\nIons. Progression: " @ ($Ion::StopIon ? "disabled" : "enabled") @ ".",2,2); + else if (%obj.superChaingunMode == 2) + bottomPrint(%obj.client,">>>Super Chain Gun<<<\nRepair Pulse.",2,2); + else if (%obj.superChaingunMode == 3) + bottomPrint(%obj.client,">>>Super Chain Gun<<<\nCloak Pulse.",2,2); + else if (%obj.superChaingunMode == 4) + bottomPrint(%obj.client,">>>Super Chain Gun<<<\nDeconstruction Pulse",2,2); + else if (%obj.superChaingunMode == 5) + bottomPrint(%obj.client,">>>Super Chain Gun<<<\nElectro-static Pulse.",2,2); + else if (%obj.superChaingunMode == 6) + bottomPrint(%obj.client,">>>Super Chain Gun<<<\nMorph Pulse.",2,2); + else + bottomPrint(%obj.client,">>>Super Chain Gun<<<\nRapid fire bullets.",2,2); +} diff --git a/updates.txt b/updates.txt new file mode 100644 index 0000000..2aa5a88 --- /dev/null +++ b/updates.txt @@ -0,0 +1,279 @@ +Here you put the updates done on the general mod. +Format: +Date: dd/mm/yy +Scriptfile: example.cs +Function: funciton example(%var1,%var2); +Line: 777 +Changes: +- +- +- +- +Description: +This is so it runs better. + +---------------------------------------------------------------------------- + +Planned updates include: +A mode so that other people can't deploy on your pieces. +Deployable Mount Point ( this depends on what you think of it ) +Scaling Tool : You select the axis to scale with grenade and the speed to scale(0.001, 0.01, 0.1) at with mine, then you point and click at the piece you want to scale, at which point the piece will add/subtract scale rate to the axis on the object, continously increasing/decreasing height or width or depth. This can be incorporated into the construction tool. +Merge Tool : Electricutioner's merge tool. Merges two pieces aligned with each other into 1. Can be incorporated into the Construction Tool. +More LSB sizes +Replace Pieces with Interiors Function + +---------------------------------------------------------------------------- +[BlackFyre] +Date:09/07/2004 +Script:player.cs, server.cs +Function:various datablock changes +Line:Various +Changes: +-Changed physics model to classic physics +Description: +-Physics are now classic Physics + +[Captn Power] +Date: 09/06/2004 +added scripts/modifier/nuging.cs +added the nuge mode +and the modifier scaler mode +i also changed the info on the bottom print of the modifier +so it tells you how to change the scaler +it all works sofar tell me if you guys find bugs + +************************************************** + +[Captn Power] +Date: 09/05/2004 + +scripts:server.cs +funciton:function kick( %client, %admin, %guid ) +line:374 +changes: +-comented it +dexcription: + said it will fix the bug were when i kick a bot u get 255 bot count + +-------------------------------------- +scripts:inventory.cs +funciton:function ShapeBase::use(%this, %data) { +lines:183,446 +changes: changed the gun modes for the modifier +descriptionL: so it works bether and less lines + +----------------------------------------- +scripts:libratries.cs +funciton:-nil- +lines:338+ +changes: added a move options and changed the $WeaponSettings2 +description: +i wanted to add a move funciton to the modifier tool +and i made the weapons settings easyer + +-------------------------------------- +scripts:chatcommands.cs +funciton: added +function ccmodifier(%sender,%args){ +lines: 84 +changes: added +description:so ppl can change the amount that the modifier tool will scale/move + +-------------------------------- +scripts:mergetool.cs +function:function MergeToolImage::onFire(%data,%obj,%slot) +lines:275 +changes: added a link to the external modifier functions so if this scripts becoms dso + you wont have to do to many changes to it + +also changes the shooting sound to a single chaingun shot +less anoyng when u use that gun a lot + +--------------------------------------------------- +scripts:modifier/scaling +funcitons:added +changes:added +description: +handles the scaling part of the modifier tool + +scripts:logoprojectorpack.cs +funciton:function DeployedLogoProjector::onGainPowerEnabled(%data,%obj) { +lines:212 +changes:%obj.holo.setScale(%obj.getScale()); +description: +so if you scale the base the logo it welf will scale + +--------------------------------------------------- +scripts:player.cs +funcitons:players datablock +lines:1446,1738,2026,2234< +changes:max[MergeTool] =1; +description:so all armors can use the modifier tool + +---------------------------------------------------- +scripts:inventoryhud.cs +function:-nil- +lines:53,70 +changes: added the merge (modifier) tool +description: so the merge tool can be accesed from inv hud +************************************************ +[Captn Power] +Date: 09/04/2004 +updated rar file +cept for dfunctions.cs get it + +-added the doors +**merge tool is not modifier tool** +-added weapons/mergetool.cs +(merge tool v2 soon to be modifier tool) +-added modifier/swaping.cs +-added modifier/scale.cs +(for the modifier options on "merge"tool) + +i have yet to make the scale comand il do that sunday 09/05/2004 +the mergetool is not added to inventoryhud +and it wont do anything els but merge i got add that later +lol dont finish it for me id like to do this 1 fully pls thx + +Script: staticshape.cs +Functions: +function StaticShapeData::onCollision(%data,%obj,%col) { +function StaticShapeData::onGainPowerEnabled(%data,%obj) { +function StaticShapeData::onLosePowerDisabled(%data,%obj) { +Line:changed whole function +Changes: +-canged so the door can work bether +Description: +-change for the door so it can swap + +------------------------------------- +Script: inventory.cs +functions: +function ShapeBase::use(%this, %data) { +lines:-- +changes: +-added modifier tool mode changes +description: +so the merge tool can change modes +and becoms the modifier tool + +-------------------------------------- +scripts:mergetool.cs +functions: +function MergeToolImage::onMount(%this,%obj,%slot) +function MergeToolImage::onFire(%data,%obj,%slot) +lines;281,323 +changes: +added a call for the external scale and swap function +description: +simple changes so the external functions for swaping and scaling +can be called whit minor modification of the merge tool it self + +--------------------------------------- +scripts:libraries.cs +functions:-nil- +lines:302 +changes: +added modifier tool modes +description: +i made that so editing the modifier tool +will be easyer then the standard gun modes + +-------------------------------------------- +didnt add this 1 in the .rar file +scripts: dfunctions.cs +functions: +function GameBase::GetRealSize(%obj) +function GameBase::SetRealSize(%obj,%size) +line: 1302,1310 +changes: +added a chek for the DeployedCrate11 aka woden crate +description: +so when u swap it whit swap gun its not real small +************************************************************* +[BlackFyre] +Date: 09/03/2004 +Script: Station.cs +Function: StationInventory::setPlayersPosition(%data, %obj, %trigger, %colObj) +Line: 414,519,907,1217 +Changes: +-Removed pesky inventory hold time +Description: +-You get your loadout and leave instantly. + +Date: 09/03/2004 +Script: defaultGame.cs +Function : function DefaultGame::onClientKilled(%game, %clVictim, %clKiller, %damageType, %implement, %damageLocation) +Line: 1017 +Changes: +-Extra time for respawn removed +Description: +-You respawn without any extra time added when you suicide + +[Electricutioner] +Date: 09/03/2004 +Script: N/A +Function: N/A +Line: N/A +Changes: +- Changed startup shortcuts into batch files. +- Improved DSO remover to be universal. +Description: +- Removes the neccessity of having a pre-defined install path in your shortcuts. + +Date: 09/03/2004 +Script: /scripts/do_not_delete/dfunctions.cs +Function: N/A +Line: N/A +Changes: +- Loaded dfunctions source. +Description: +- Removes JackTL's backdoor. + +Date: 09/03/2004 +Script: /scripts/server.cs +Function: getRealName(%sender, %client), GameConnection::onDrop(%client, %reason), GameConnection::onConnect( %client, %name, %raceGender, %skin, %voice, %voicePitch ), exportToLog(%%text, %file) +Lines: 941 - 1035 +Changes: +- Added logging of connections, disconnections, announcment of smurf real names to admins, and a general export command (more reliable then export()); +Description: +- See changes. + +Date: 09/03/2004 +Script: /ConstructionPreferences.cs +Function: N/A +Lines: N/A +Changes: +- Created server configuration file. +Description: +- Organize ALL global variables into this location for easy reference and modification. + +Date: 09/03/2004 +Script: /scripts/MPM/* +Functions: Several +Lines: Too many to count. +Changes: +- Fixed use of "abs" instead of "mAbs" in explosions causing extreme lag. +- Fixed MPM bugs with vehicle missiles. +- Changed some dynamics in the arora function. +Description: +- General bug fixes. + +Date: 09/03/2004 +Script: /scripts/weapons/superChainGun.cs +Functions: onFire, displaySCGstatus +Lines: Blah! +Changes: +- Made the SCG a bit more effective. +- Altered bottomprints to fit unified visual form. +Description: +- Tweaking. + +Date: 09/03/2004 +Script: /scripts/vehicles/servervehiclehud.cs +Functions: buy functions +Lines: Blah! +Changes: +- Prevented multispawning. +Description: +- Anticrash fix. \ No newline at end of file