Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- @name WPD Spinner Code V3.1.3
- @inputs Mouse1 Mouse2 DualInput R
- @inputs [Weapon,Chassis,Shell,Support1,Support2,SupportAxle]:entity
- @outputs WeaponTorque:angle ChassisTorque:angle Sound PitchRelative DamageMultiplier WeaponRPM
- @outputs WeaponInertia:vector WeaponRadius TipSpeed StallCounter
- @outputs WeaponMaxHealth WeaponDamage ChassisMaxHealth ChassisDamage Support1MaxHealth Support1Damage
- @outputs Support2MaxHealth Support2Damage SupportAxleMaxHealth SupportAxleDamage Smoke Alive
- @persist WeaponRPM_Old WeaponRPM_Delta WeaponRPM_Check StallPowerMul SB_Mul RPMCount
- @persist SpinPower Pitch Yaw Roll AirDrag StatusMessages ManualInertia ChassisSpinPower
- @persist Power SpinPowerMul TorqueMul ChassisRPM WeaponRPMVec:angle WeaponRPMAng
- @persist Shell_Exists Support1_Exists Support2_Exists SupportAxle_Exists SupportsConstrained
- @persist Stall StallRate StallPercentage DeathCheck TimerDelay SpikeballType MaxRPM InertiaState
- @persist StallRateVar StallCountDownRate StallCountThreshold StallRPMCheck
- @persist MaxInertia InertiaUsed [NaturalInertia,ArtificialInertia]:vector
- @persist InertiaMul InertiaTorqueMul [PropTable,InertiaTable]:table TableSize
- @persist PYR_Correct [PYR_Weapon, PYR_Chassis]:angle Duped [SpinAxis]:vector
- @persist HalfSpeedMul WPDInertia InertiaDamageMultiplier WPD_Mul
- @persist ChassisHits Support1Hits Support2Hits SupportAxleHits
- @persist LastDamage:vector Spikeball_Drag Spikeball_Active CounterTorqueMul
- @persist StandardRPM RPMCheck RPM_High GrindMul PhysicalProperty:string
- @persist BotActive Physgun SawMode PR_Mul HeavyDrag DragLoop_Low DragLoop_High DragLoop_Count
- @persist ShellAxis:vector PYR_Shell:angle WeaponWidth ShellRadius
- @persist WPDShellInertia MaxShellInertia DamageThreshold ShellMul Start
- @persist [DefaultInertia,StallInertia]:vector SmokeCheck TopSpeed
- @persist [Shell_DefaultInertia,Shell_StallInertia,Shell_WeaponInertia]:vector
- @persist WeaponHits AxleBroken WeaponBroken ShellBroken FirstInput
- @persist Stats_RPM Stats_MOI Stats_Diameter Stats_KE Stats_Mass NormalDrag
- @persist ServerRPMLimit
- WeaponInput=(Mouse1-Mouse2+DualInput)
- if(dupefinished()|WeaponInput!=0|R==1){Start=1}elseif(duped()){Start=0}
- if(first()|dupefinished()|R==1|inputClk()&changed(WeaponInput)==0){
- runOnTick(1)
- #DISCLAIMER FROM BUSINESS CAT:
- #Counter Rotation Code works so that the spinner can spin the chassis when nearly stalled
- #Counter-torque value is determined by the inertia of your spinner - more inertia means more counter-torque.
- #Stall edition makes the spinner possibly break itself IF:
- #the spin key is held too long when the blade/chassis cannot spin freely.
- #Your weapon motor would be very unhappy with you if you did that.
- #YOU WILL HAVE TO WIRE A BUTTON TO REVIVE YOUR SPINNER ONCE IT HAS STALLED.
- #While you can wire it to R on your pod controller,
- #having the ability to 'fix' the stall mid-fight is unfair and unrealistic.
- #Put the button on the robot to prevent this unfair advantage.
- #==============================================================================================================
- #USER SETTINGS - ONLY CHANGE THE VALUES IN THIS SECTION
- #==============================================================================================================
- #IT IS RECOMMENDED THAT YOU RESPAWN THE BOT AFTER SWITCHING TO THIS CODE FROM THE OLD VERSION
- InertiaUsed = 0 #Custom set inertia, set to 1 to enable it, 0 to disable
- ManualInertia = 500 #INERTIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA (Up to 1000 permitted)
- TipSpeed = 250 #If your spinner is unstable at high speeds, lower this (Max = 250mph)
- Pitch = 0 #Use these to select which axis your weapon spins on
- Yaw = 1 #Set the one you want to '1' and the others to '0'
- Roll = 0 #If your weapon doesn't spin, try selecting a different axis
- Power = 500000 #Add/Remove a negative if blade is spinning the wrong way
- AirDrag = 0.15 #Change this to change how quickly the spinner slows down
- StatusMessages = 1 #Set this to 0 to turn off stall % readouts in chat. 1 is on.
- StallRateVar = 16 #DO NOT CHANGE unless switching weight classes
- SawMode = 0 #Set to '1' if the spinner is being used as a saw
- #==============================================================================================================
- # !!!DO NOT TOUCH ANYTHING BELOW!!!
- #==============================================================================================================
- #Saw Mode - Initial Setup
- if(SawMode==1){ #Auto-modifies settings to make saws more stable
- AirDrag = AirDrag+5
- InertiaUsed = 1
- StallRateVar = 0
- ManualInertia = 20}
- #=====================
- #Air Drag - Initial Setup
- Weapon:setCustomAirDrag(1,0,AirDrag)
- HeavyDrag = 5
- DragLoop_Low = 0
- DragLoop_High = 0
- DragLoop_Count = 0
- #=====================
- #Physical Properties - Initial Setup
- PhysicalProperty = "metalgrate"
- Weapon:propPhysicalMaterial(PhysicalProperty)
- #=====================
- #Supports - Initial Setup
- if(Shell:isValid()){Shell_Exists=1}else{Shell_Exists=0} #Checks whether shell exists at startup
- if(Support1:isValid()){Support1_Exists=1}else{Support1_Exists=0} #Checks whether each support exists at startup
- if(Support2:isValid()){Support2_Exists=1}else{Support2_Exists=0}
- if(SupportAxle:isValid()){SupportAxle_Exists=1}else{SupportAxle_Exists=0} #Checks whether one support is an axle
- if((Support1_Exists+Support2_Exists+SupportAxle_Exists)==0){SupportsConstrained=0}
- else{SupportsConstrained=1}
- AxleBroken = 0
- WeaponBroken = 0
- ShellBroken = 0
- BotActive = 0
- FirstInput = 0
- #=====================
- #Pitch/Yaw/Roll - Initial Setup
- if(Power>500000){Power=500000} #Prevents cheating
- if(Power<-500000){Power=-500000} #Prevents cheating
- if(first()){
- if((Pitch+Yaw+Roll)!=1){print("----------WARNING----------\nFor the spinner to work, only one of the Pitch/Yaw/Roll settings should be set to '1'.",
- "The others must be set to '0'. ","\n\nThe current settings are:","\nPitch","=",Pitch, "\nYaw","=",Yaw, "\nRoll","=",Roll)
- ,PYR_Correct=0}
- else{PYR_Correct=1}
- }
- if(Shell_Exists==0){ #Spinner is not a shell
- SpinAxis=vec(Roll,Pitch,Yaw) #Gets weapon rotation axis as local vector
- SpinAxis=(Weapon:toWorldAxis(SpinAxis)) #Converts to global axis
- SpinAxis=(Chassis:toLocalAxis(SpinAxis)):normalized() #Converts to local chassis axis
- SpinAxis=round(SpinAxis,2) #Rounds to 2dp to prevent 'leakage' into other axes when not required
- }
- else{ #Spinner is a shell
- SpinAxis=vec(Roll,Pitch,Yaw) #Gets weapon rotation axis as local vector
- SpinAxis=(Shell:toWorldAxis(SpinAxis)) #Converts to global axis
- SpinAxis=(Chassis:toLocalAxis(SpinAxis)):normalized() #Converts to local chassis axis
- SpinAxis=round(SpinAxis,2) #Rounds to 2dp to prevent 'leakage' into other axes when not required
- ShellAxis=vec(Roll,Pitch,Yaw) #Gets weapon rotation axis as local vector
- ShellAxis=(Shell:toWorldAxis(ShellAxis)) #Converts to global axis
- ShellAxis=(Weapon:toLocalAxis(ShellAxis)):normalized() #Converts to local chassis axis
- ShellAxis=round(ShellAxis,2) #Rounds to 2dp to prevent 'leakage' into other axes when not required
- }
- PYR_Weapon=ang(Pitch,Yaw,Roll)
- PYR_Shell=ang(ShellAxis:y(),ShellAxis:z(),ShellAxis:x())
- PYR_Chassis=ang(SpinAxis:y(),SpinAxis:z(),SpinAxis:x())
- #=====================
- #Effective Weapon Radius - Initial Setup
- BoxSize=Weapon:boxSize()
- BoxCentre=Weapon:boxCenter()
- MassCentre=Weapon:massCenterL()
- ShellRadius=max(Shell:boxSize():x(),Shell:boxSize():y(),Shell:boxSize():z())/2*0.01905
- X_Diff=abs(BoxCentre:x()-MassCentre:x())
- Y_Diff=abs(BoxCentre:y()-MassCentre:y())
- Z_Diff=abs(BoxCentre:z()-MassCentre:z())
- if(Pitch==1){
- if(BoxSize:x()>=BoxSize:z()){
- WeaponRadius=sqrt((BoxSize:x()/2+X_Diff)^2+(BoxSize:z()/4)^2) #Estimates the effective radius of the weapon
- WeaponRadius=WeaponRadius*0.01905 # Converts effective radius from source units to metres
- WeaponWidth=BoxSize:z()*0.01905} # Finds width of weapon for calculating MOI
- else{
- WeaponRadius=sqrt((BoxSize:z()/2+Z_Diff)^2+(BoxSize:x()/4)^2) #Estimates the effective radius of the weapon
- WeaponRadius=WeaponRadius*0.01905 # Converts effective radius from source units to metres
- WeaponWidth=BoxSize:x()*0.01905} # Finds width of weapon for calculating MOI
- }
- if(Yaw==1){
- if(BoxSize:x()>=BoxSize:y()){
- WeaponRadius=sqrt((BoxSize:x()/2+X_Diff)^2+(BoxSize:y()/4)^2) #Estimates the effective radius of the weapon
- WeaponRadius=WeaponRadius*0.01905 # Converts effective radius from source units to metres
- WeaponWidth=BoxSize:y()*0.01905} # Finds width of weapon for calculating MOI
- else{
- WeaponRadius=sqrt((BoxSize:y()/2+Y_Diff)^2+(BoxSize:x()/4)^2) #Estimates the effective radius of the weapon
- WeaponRadius=WeaponRadius*0.01905 # Converts effective radius from source units to metres
- WeaponWidth=BoxSize:x()*0.01905} # Finds width of weapon for calculating MOI
- }
- if(Roll==1){
- if(BoxSize:z()>=BoxSize:y()){
- WeaponRadius=sqrt((BoxSize:z()/2+Z_Diff)^2+(BoxSize:y()/4)^2) #Estimates the effective radius of the weapon
- WeaponRadius=WeaponRadius*0.01905 # Converts effective radius from source units to metres
- WeaponWidth=BoxSize:y()*0.01905} # Finds width of weapon for calculating MOI
- else{
- WeaponRadius=sqrt((BoxSize:y()/2+Y_Diff)^2+(BoxSize:z()/4)^2) #Estimates the effective radius of the weapon
- WeaponRadius=WeaponRadius*0.01905 # Converts effective radius from source units to metres
- WeaponWidth=BoxSize:z()*0.01905} # Finds width of weapon for calculating MOI
- }
- if(Shell_Exists==1){ #For shell, just finds largest 2 directions for length/width since orientation is more predictable
- if(BoxSize:x()>BoxSize:y()&BoxSize:x()>BoxSize:z()){
- if(BoxSize:y()>BoxSize:z()){
- WeaponWidth=BoxSize:y()*0.01905}
- else{WeaponWidth=BoxSize:z()*0.01905}
- }
- elseif(BoxSize:y()>BoxSize:x()&BoxSize:y()>BoxSize:z()){
- if(BoxSize:x()>BoxSize:z()){
- WeaponWidth=BoxSize:x()*0.01905}
- else{WeaponWidth=BoxSize:z()*0.01905}
- }
- else{
- if(BoxSize:y()>BoxSize:z()){
- WeaponWidth=BoxSize:y()*0.01905}
- else{WeaponWidth=BoxSize:z()*0.01905}
- }
- WeaponRadius=max(BoxSize:x(),BoxSize:y(),BoxSize:z())*0.01905/2
- }
- if(WeaponRadius>3){WeaponRadius=3}
- if(WeaponWidth>3){WeaponWidth=3}
- #=====================
- #RPM - Initial Setup
- if(TipSpeed>250){TipSpeed=250}
- StandardRPM = 660 #Empirical standard value found through testing
- MaxRPM = round((TipSpeed/250)*StandardRPM*(3/WeaponRadius),0)
- ServerRPMLimit=angSpeedLimit()/6 #6 divisor converts from degrees/s to RPM
- if(MaxRPM<1250){MaxRPM=1250*(TipSpeed/250)}
- elseif(MaxRPM>3300){MaxRPM=3300}
- elseif(MaxRPM>ServerRPMLimit){MaxRPM=ServerRPMLimit}
- if(Shell_Exists==0){
- if(Pitch==1){
- WeaponRPM = abs((Weapon:angVel():pitch()/6))
- ChassisRPM = abs((Chassis:angVel()*PYR_Chassis/6):pitch())}
- elseif(Yaw==1){
- WeaponRPM = abs((Weapon:angVel():yaw()/6))
- ChassisRPM = abs((Chassis:angVel()*PYR_Chassis/6):roll())}
- else{
- WeaponRPM = abs((Weapon:angVel():roll()/6))
- ChassisRPM = abs((Chassis:angVel()*PYR_Chassis/6):yaw())}
- }
- else{
- if(Pitch==1){
- WeaponRPM = abs((Shell:angVel():pitch()/6))
- ChassisRPM = abs((Chassis:angVel()*PYR_Chassis/6):pitch())}
- elseif(Yaw==1){
- WeaponRPM = abs((Shell:angVel():yaw()/6))
- ChassisRPM = abs((Chassis:angVel()*PYR_Chassis/6):roll())}
- else{
- WeaponRPM = abs((Shell:angVel():roll()/6))
- ChassisRPM = abs((Chassis:angVel()*PYR_Chassis/6):yaw())}
- }
- if(MaxRPM>1800){MaxRPM=1800} #Mitigates wobbling
- LowRPMCheck = MaxRPM * 0.1
- CounterTorqueMul = 1
- PR_Mul = 0.85*MaxRPM #Multiplier for PitchRelative Calc (Saves a couple ops)
- #=====================
- #Inertia - Initial Setup
- if(first()&InertiaUsed==0){print("----------WARNING----------\nYou are set to natural inertia. After first updating the E2, you will need to: \n1) Reset the weapon's inertia using the Inertia tool \n2) Press the weapon reset button on the robot")}
- if(ManualInertia>1000){ManualInertia=1000} #Prevents setting manual inertia above 1000
- InertiaState=0
- if(InertiaUsed==1){InertiaMul=1,InertiaTorqueMul=2,SpinPowerMul=1}
- else{InertiaMul=1.75,InertiaTorqueMul=2,SpinPowerMul=1}
- if(WeaponRPM>=LowRPMCheck){ #Prevents bugs when E2 or R reset while spinning
- print("----------WARNING----------\nWeapon must come to a stop before pressing reset or changing the E2 chip settings")
- if(InertiaUsed==1){
- DefaultInertia = vec(ManualInertia) #Low speed inertia (default - prevents bugs)
- WeaponInertia = DefaultInertia*InertiaMul #High speed inertia (Gets default inertia & multiplier)
- Shell_DefaultInertia = vec(ManualInertia)
- Shell_WeaponInertia = Shell_DefaultInertia*InertiaMul}
- else{
- DefaultInertia = Weapon:inertia()/InertiaMul
- WeaponInertia = DefaultInertia*InertiaMul
- Shell_DefaultInertia = Shell:inertia()/InertiaMul
- Shell_WeaponInertia = Shell_DefaultInertia*InertiaMul}
- }
- else{
- if(InertiaUsed==1){
- DefaultInertia = vec(ManualInertia)
- WeaponInertia = DefaultInertia*InertiaMul
- Weapon:propInertia(DefaultInertia)
- Shell_DefaultInertia = vec(ManualInertia)
- Shell_WeaponInertia = Shell_DefaultInertia*InertiaMul
- Shell:propInertia(DefaultInertia)}
- else{
- DefaultInertia = Weapon:inertia()
- WeaponInertia = DefaultInertia*InertiaMul
- Shell_DefaultInertia = Shell:inertia()
- Shell_WeaponInertia = Shell_DefaultInertia*InertiaMul}
- }
- if(Shell_Exists==0){
- Shell_DefaultInertia = vec(0,0,0)
- Shell_WeaponInertia = vec(0,0,0)
- if(Pitch==1){WPDInertia=WeaponInertia:y()}
- elseif(Yaw==1){WPDInertia=WeaponInertia:z()}
- else{WPDInertia=WeaponInertia:x()}
- MaxInertia=WPDInertia
- }
- else{
- if(Pitch==1){WPDInertia=Shell_WeaponInertia:y()}
- elseif(Yaw==1){WPDInertia=Shell_WeaponInertia:z()}
- else{WPDInertia=Shell_WeaponInertia:x()}
- MaxInertia=WPDInertia+max((WeaponInertia*ShellAxis):x(),(WeaponInertia*ShellAxis):y(),(WeaponInertia*ShellAxis):z())
- }
- Physgun=0
- #=====================
- #Stall - Initial Setup
- if(Shell_Exists==1){ShellMul = 1}
- else{ShellMul=1}
- StallRate = (1)/sqrt(1500)*StallRateVar/ShellMul
- StallCountDownRate = 0.5
- StallCountThreshold = 100
- StallRPMCheck = MaxRPM*0.1 #RPM below which weapon starts to stall
- RPMCheck = 15 #RPM below which counter-torque applied
- TorqueMul = 1200*1500*(WeaponRadius/3)*Power/abs(Power) #Changes sign if necessary
- StallPowerMul = 1
- if(first()|dupefinished())
- {StallCounter=0,Stall=0,Alive=1,Smoke=0,SmokeCheck=0,DeathCheck=0} #Resets the stall code
- #=====================
- #Spikeballing Fix - Initial Setup
- LastDamage = vec(0,0,0)
- Spikeball_Drag = 10-10*(WeaponRadius/3) #Gives 1 drag for 6m diameter weapons, and 10 drag at 0m.
- RPM_High = 0
- Spikeball_Active = 0
- Spikeball_Mul = 1
- SB_Mul = 0
- #=====================
- #WPD - Initial Setup
- HealthBoost = 35000 #Health that WPD props are boosted to (allows advanced destruction effects)
- DamageThreshold = 200 #Minimum damage that a hit needs to have to break a prop off
- InertiaDamageMultiplier = 2.4*(MaxInertia/1000)*(MaxRPM/1800)^2*(250/TipSpeed)^2 #Scales damage based off inertia and RPM, (takes tip speed as 250)
- GrindMul = 1 #Reduces damage for multiple hits in quick succession
- if(InertiaDamageMultiplier > 1.5){InertiaDamageMultiplier=1.5} #Max Multiplier = 1.5
- Weapon:registerDamageMonitor()
- Weapon:setDamagePropHealth(HealthBoost)
- Weapon:setDamageParticleEffect("wpd_sparkx_big")
- Weapon:setDamageParticleEffectThreshold(100,"wpd_sparkx_huge")
- Weapon:bypassWorldDamageFX(0)
- WeaponMaxHealth=27000*0.6 #0.6 multiplier as props normally fall off at 40% health
- WeaponHits=0
- if(SawMode==1){
- Weapon:registerDamageMonitor()
- Weapon:setDamagePropHealth(HealthBoost*2)
- Weapon:setDamageParticleEffect("wpd_sparkx_huge")
- Weapon:setDamageParticleEffectThreshold(100,"wpd_sparkx_huge")
- Weapon:bypassWorldDamageFX(0)
- WeaponMaxHealth=HealthBoost*2
- WeaponHits=0
- InertiaDamageMultiplier=1.5}
- Chassis:registerDamageMonitor()
- Chassis:setDamagePropHealth(HealthBoost)
- ChassisMaxHealth=Chassis:mass()*30*0.6
- ChassisHits=0
- Support1:registerDamageMonitor()
- Support1:setDamagePropHealth(HealthBoost)
- Support1MaxHealth=Support1:mass()*30*0.6
- Support1Hits=0
- Support2:registerDamageMonitor()
- Support2:setDamagePropHealth(HealthBoost)
- Support2MaxHealth=Support2:mass()*30*0.6
- Support2Hits=0
- SupportAxle:registerDamageMonitor()
- SupportAxle:setDamagePropHealth(HealthBoost)
- SupportAxleMaxHealth=SupportAxle:mass()*30*0.6
- SupportAxleHits=0
- if(first()|dupefinished()){WPD_Mul=1} #Allows spin power to be reduced when damage taken: Starts at 1 (=100% power)
- #=====================
- #Weapon Stats - Initial Setup
- #Calculates the stats that weapon would have in real life
- Stats_Mass = round(Weapon:mass()+Shell:mass(),0)/10 #Divide by 10, simple
- Stats_Diameter = round(WeaponRadius,2)*1000*2/5 #5:1 GMod to IRL scale; 1:1000 converts m to mm; *2 finds diameter from radius
- Stats_RPM = round(0.44704*(TipSpeed*60)/(pi()*Stats_Diameter/1000),0) #*0.44704 from unit conversion
- Stats_MOI = round((0.5*Shell:mass()/10*(ShellRadius/5)^2)+(Weapon:mass()/10/12)*((WeaponWidth*0.7/5)^2+((Stats_Diameter/1000)^2)),2) #0.7 mult rovides good all-around estimate for discs+bars
- Stats_KE = round((0.1047198^2)*(0.5*Stats_MOI*Stats_RPM^2)/1000,1) #0.1047198^2 multiplier converts units to kJ
- #==============================================================================================================================
- } #End of initial setups
- #==============================================================================================================================
- #Inputs Section
- if(Start==1){ #Encapsules all code below - prevents bug
- ChassisSpinPower = TorqueMul*(1-PitchRelative)
- if(WeaponInput!=0){BotActive=1}
- else{BotActive=0}
- if(BotActive==1){FirstInput=1}
- #=====================
- #Support Break Code
- if(FirstInput==1){ #Doesn't run until after first input
- if(SupportAxle_Exists==1){
- if(Support1_Exists+Support2_Exists==2){ #If bot has 2 frame supports:
- if((Support1:hasConstraints("weld")==0&Support1:hasConstraints("axis")==0)&
- (Support2:hasConstraints("weld")==0&Support2:hasConstraints("axis")==0)) #If both supports break, weapon + axle get detached
- {
- AxleBroken=1
- WeaponBroken=1
- ShellBroken=1
- SupportsConstrained=0
- }
- elseif((Support1:hasConstraints("weld")==0&Support1:hasConstraints("axis")==0)|
- (Support2:hasConstraints("weld")==0&Support2:hasConstraints("axis")==0)) #If one support breaks, weapon stays attached but dies
- {SupportsConstrained=0}
- if(SupportAxle:hasConstraints("weld")==0&SupportAxle:hasConstraints("axis")==0) #If axle breaks, weapon gets detached
- {
- WeaponBroken=1
- ShellBroken=1
- SupportsConstrained=0
- }
- }
- elseif(Support1_Exists+Support2_Exists==1){ #If only one frame support:
- if( (Support1_Exists==1&Support1:hasConstraints("weld")==0&Support1:hasConstraints("axis")==0) | # If the frame support breaks,
- (Support2_Exists==1&Support2:hasConstraints("weld")==0&Support2:hasConstraints("axis")==0) ) # both Weapon and Axle get broken off
- {
- AxleBroken=1
- WeaponBroken=1
- ShellBroken=1
- SupportsConstrained=0
- }
- if(SupportAxle:hasConstraints("weld")==0&SupportAxle:hasConstraints("axis")==0) #If axle breaks, weapon gets detached
- {
- WeaponBroken=1
- ShellBroken=1
- SupportsConstrained=0
- }
- }
- if(AxleBroken==1){
- SupportAxle:constraintBreak("axis")
- SupportAxle:constraintBreak("ballsocket")
- SupportAxle:constraintBreak("weld")
- SupportAxle:constraintBreak("rope")
- SupportAxle:constraintBreak("AdvBallsocket")
- SupportAxle:constraintBreak("advballsocket")
- SupportAxle:setDamagePropHealth(SupportAxleMaxHealth)}
- }
- elseif( #If no axle, function as normal
- (Support1_Exists==1&Support1:hasConstraints("weld")==0&Support1:hasConstraints("axis")==0) |
- (Support2_Exists==1&Support2:hasConstraints("weld")==0&Support2:hasConstraints("axis")==0) )
- {
- WeaponBroken=1
- ShellBroken=1
- SupportsConstrained=0
- }
- if(WeaponBroken==1){
- Weapon:constraintBreak("axis")
- Weapon:constraintBreak("ballsocket")
- Weapon:constraintBreak("weld")
- Weapon:constraintBreak("rope")
- Weapon:constraintBreak("AdvBallsocket")
- Weapon:constraintBreak("advballsocket")
- Weapon:setDamagePropHealth(WeaponMaxHealth)}
- }
- if(SupportsConstrained == 0){WeaponSpinMul=0}
- else{WeaponSpinMul=1} #Death settings based on one/two support deaths, or chassis/weapon death
- #=====================
- #Shell Break Code
- if(Shell_Exists==1){
- if(ShellBroken==1){ #If support broken, break shell
- Shell:constraintBreak("axis")
- Shell:constraintBreak("ballsocket")
- Shell:constraintBreak("weld")
- Shell:constraintBreak("rope")
- Shell:constraintBreak("AdvBallsocket")
- Shell:constraintBreak("advballsocket")
- SupportsConstrained=0}
- if(Shell:hasConstraints("axis")==0){ #If shell broken, break weapon
- Weapon:constraintBreak("axis")
- Weapon:constraintBreak("ballsocket")
- Weapon:constraintBreak("weld")
- Weapon:constraintBreak("rope")
- Weapon:constraintBreak("AdvBallsocket")
- Weapon:constraintBreak("advballsocket")
- Weapon:setDamagePropHealth(WeaponMaxHealth)
- SupportsConstrained=0
- WeaponBroken=1}
- }
- #=====================
- #RPM Code
- if(Shell_Exists==0){
- if(Pitch==1){
- WeaponVel = Weapon:angVel():pitch()/6
- WeaponRPM = abs(WeaponVel)
- ChassisRPM = abs((Chassis:angVel()*PYR_Chassis/6):pitch())
- }
- elseif(Yaw==1){
- WeaponVel = Weapon:angVel():yaw()/6
- WeaponRPM = abs(WeaponVel)
- ChassisRPM = abs((Chassis:angVel()*PYR_Chassis/6):roll())
- }
- else{
- WeaponVel = Weapon:angVel():roll()/6
- WeaponRPM = abs(WeaponVel)
- ChassisRPM = abs((Chassis:angVel()*PYR_Chassis/6):yaw())
- }
- }
- else{
- if(Pitch==1){
- WeaponVel = Shell:angVel():pitch()/6
- WeaponRPM = abs(WeaponVel)
- ChassisRPM = abs((Chassis:angVel()*PYR_Chassis/6):pitch())
- }
- elseif(Yaw==1){
- WeaponVel = Shell:angVel():yaw()/6
- WeaponRPM = abs(WeaponVel)
- ChassisRPM = abs((Chassis:angVel()*PYR_Chassis/6):roll())
- }
- else{
- WeaponVel = Shell:angVel():roll()/6
- WeaponRPM = abs(WeaponVel)
- ChassisRPM = abs((Chassis:angVel()*PYR_Chassis/6):yaw())
- }
- }
- if(WeaponRPM>20){Sound=1}
- else{Sound=0}
- PitchRelative=WeaponRPM/PR_Mul
- if(PitchRelative>1){PitchRelative=1}
- CounterTorqueMul=1-PitchRelative
- if(CounterTorqueMul<0.05){CounterTorqueMul=0.05}
- if(PitchRelative==1){TopSpeed=1}
- else{TopSpeed=0}
- if(changed(TopSpeed)){
- if(TopSpeed==1){Weapon:setDamageParticleEffect("wpd_sparkx_huge")}
- else{Weapon:setDamageParticleEffect("wpd_sparkx_big")}
- }
- #=====================
- #Inertia Code
- WeaponMass=Weapon:mass()
- if(WeaponMass<2000){ #Prevents physgun bugs
- if((WeaponRPM<StallRPMCheck)&WeaponInput==0){InertiaState=1} #RPM low and weapon inactive: Default Inertia
- else{InertiaState=2} #Otherwise: High Inertia
- }
- if(changed(InertiaState)){ #Only applies inertia when InertiaState changes - saves performance
- if(InertiaState==1){Weapon:propInertia(DefaultInertia)}
- else{Weapon:propInertia(WeaponInertia)}
- }
- if(WeaponMass>2000){Physgun=1}
- if(changed(WeaponMass)){
- if(Physgun==0){
- if(first()==0&dupefinished()==0&R!=1){
- if(WeaponMass!=0){
- print("----------WARNING----------\nAfter changing the weapon's mass, you will need to:\n1) Reset the weapon's inertia using the Inertia tool\n2) Press the weapon reset button on the robot")}
- }
- }
- elseif(WeaponMass<2000){Physgun=0}
- }
- #=====================
- #Stall Code
- if(Stall==1){
- if(clk("DeathTime")){print("Weapon Stall:\t100\t%"),DeathCheck=1} #Tells you that you died
- if(DeathCheck!=1){timer("DeathTime",100),SmokeCheck=1}
- }
- else{
- if(WeaponInput!=0 & WeaponRPM<(StallRPMCheck) & ChassisRPM<(StallRPMCheck))
- {StallCounter=StallCounter+StallRate} #Counts up
- else{StallCounter=StallCounter-(StallRate*StallCountDownRate)} #Counts down
- if(StallCounter>0){
- timer("Clock",200)
- if(StallCounter>StallCountThreshold){Stall=1,Alive=0} #if threshold is hit, you die
- }
- #if you are reading this then I appreciate you
- else{StallCounter=0} #no negative count allowed
- if(clk("Clock") & StatusMessages==1){
- StallPercentage = round((StallCounter/StallCountThreshold)*100)
- print("Weapon Stall:",StallPercentage,"%")} #displays % in chat
- }
- if(changed(R)){
- if(R==1){StallCounter=0,Stall=0,Alive=1,Smoke=0,SmokeCheck=0,DeathCheck=0,print("Weapon Status:\tActive") #Resets the stall code
- if(StatusMessages==1){print("-----Real Life Stats-----","\nMass (kg):\t\t",Stats_Mass,"\nMax RPM:\t\t",Stats_RPM,"\nDiameter (mm):\t",Stats_Diameter,"\nTip Speed (mph):\t",TipSpeed,"\nMOI (kg.m^2):\t",Stats_MOI,"\nKinetic Energy (kJ): ",Stats_KE)}
- }
- }
- #the Smoke output lets you wire a numpad output to it, and then you can place a particle controller
- #with the same key as the numpad output - and when your spinner stalls, it will let out a puff of smoke
- #cool innit?
- #=====================
- #AirDrag Feedback Loop Code
- #If air drag is too high, sound pitch oscillates constantly at high speed
- #If air drag is too low, wobble occurs
- if(WeaponRPM>MaxRPM+100){DragLoop_Low=1} #Checks if RPM is going too high, means Drag is too low (causes wobble)
- else{DragLoop_Low=0}
- if(DragLoop_High==0){
- if(PitchRelative==1){DragLoop_High=1}} #This section checks for sound glitch (caused by air drag being too high)
- if(DragLoop_High==1){
- if(PitchRelative<1){DragLoop_High=2}}
- if(DragLoop_High==2){
- if(PitchRelative<0.80){DragLoop_High==0} #If PitchRelative drops back down without oscillating, air drag probably ok
- if(PitchRelative==1){DragLoop_High=3}} #If PitchRelative increases again quickly, sound glitch is probably occurring
- if(changed(DragLoop_Low)){
- if(DragLoop_Low==1){HeavyDrag=HeavyDrag+0.5}} #Increases Air Drag until wobble stops
- if(changed(DragLoop_High)){
- if(DragLoop_High==3){HeavyDrag=HeavyDrag-0.5,DragLoop_High=0}} #Decreases Air Drag until sound gltich stops
- DragLoop_Low=0
- if(HeavyDrag<3){HeavyDrag=3}
- if(HeavyDrag>10){HeavyDrag=10}
- #=====================
- #Spikeballing/Grinding Fix Code
- LastDamage = Weapon:getEntityDamagePosition() #Checks for collision (each hit will always be slightly diff position)
- if(changed(LastDamage)){
- if(((Weapon:getDamageInflictor()):type())!="prop_physics"){ #Applies drag for 100ms if spinner hit the world
- timer("Drag_Time",100)
- stoptimer("Stall_Time")
- timer("Stall_Time",500)
- StallPowerMul = WeaponRadius/3 #Reduces torque if obstructed below 50% RPM (1.25 factor as torque is 2x higher but gravity only 1.6x higher)
- SB_Mul = SB_Mul + 0.2
- SpikeballType = 1
- if(SB_Mul==0.2){SB_Mul=0.01}} #Reduces SB_Mul for the first bounce
- else{ #Applies different drag for 150ms if spinner hits anything else
- timer("Drag_Time",150)
- timer("Grind_Time",100) #Reduces damagemul to 10% after a hit, and increases it by 10% every 100ms after
- SB_Mul = 0
- GrindMul = 0.5
- SpikeballType = 2}
- }
- elseif(SpikeballType==3|SpikeballType==0){
- if(RPM_High==1){SpikeballType=3}
- else{SpikeballType=0}
- }
- if(clk("Drag_Time")){SpikeballType=0}
- if(clk("Grind_Time")){GrindMul=GrindMul+0.1
- if(GrindMul>1){GrindMul=1}
- else{timer("Grind_Time",100)}
- }
- WorldDrag=Spikeball_Drag*SB_Mul
- if(SawMode==1){
- SpikeballType=0
- GrindMul=1}
- if(WeaponInput==0){NormalDrag=AirDrag} #Fixes bug, don't touch
- else{NormalDrag=0} #
- if(changed(SpikeballType)){
- if(SpikeballType==0){
- Weapon:setCustomAirDrag(1,0,NormalDrag) #Resets to default
- Chassis:setCustomAirDrag(1,0,0)}
- elseif(SpikeballType==1){
- Weapon:setCustomAirDrag(1,0,WorldDrag) #Spinner hits the world - Adds rotation drag
- Chassis:setCustomAirDrag(1,WorldDrag,0)} #Adds linear drag to chassis to avoid cross-arena spikeballing
- elseif(SpikeballType==2){
- Weapon:setCustomAirDrag(1,3*Spikeball_Drag*PitchRelative,AirDrag) #Spinner hits player props - Adds linear drag to weapon
- Chassis:setCustomAirDrag(1,0,Spikeball_Drag*1000)} #Adds rotation drag to chassis - prevents backflips
- elseif(SpikeballType==3){
- Weapon:setCustomAirDrag(1,0,HeavyDrag) #Spinner goes above rpm limit - applies drag to prevent wobble
- Chassis:setCustomAirDrag(1,0,0)}
- }
- elseif(SpikeballType==0){
- Weapon:setCustomAirDrag(1,0,NormalDrag) #Resets to default
- Chassis:setCustomAirDrag(1,0,0)}
- #=====================
- #Weapon Spin Code
- if(WeaponRPM<MaxRPM){RPM_High=0}
- else{RPM_High=1}
- if(tickClk()){
- WeaponRPM_Delta=abs(WeaponVel-WeaponRPM_Old) #Finds RPM difference over the last tick
- WeaponRPM_Check=abs(1000*WeaponRPM_Delta*MaxInertia/SpinPower) #Checks whether spinner is obstructed
- WeaponRPM_Old=WeaponVel #Records RPM for next tick comparison
- if(WeaponRPM_Check<3&WeaponInput!=0){RPMCount=RPMCount+1}
- else{RPMCount=0}
- if((PitchRelative<0.5) & (RPMCount>1) & SB_Mul!=0 & WeaponInput!=0 & changed(WeaponInput)==0){ #Normal value is ~6, so <3 means the weapon is obstructed
- stoptimer("Stall_Time")
- timer("Stall_Time",200)
- StallPowerMul=WeaponRadius/3} #Reduces torque if obstructed below 50% RPM
- }
- if(clk("Stall_Time")){StallPowerMul=1}
- if(SawMode==1){StallPowerMul=1}
- if(BotActive==1){
- if(PitchRelative==1){
- if(SawMode==0){SpinPowerMul=5}
- else{SpinPowerMul=0}}
- else{SpinPowerMul=1}
- SpinPower = Power*InertiaTorqueMul*SpinPowerMul*StallPowerMul*WPD_Mul
- WeaponTorque=(WeaponInput*SpinPower*WeaponSpinMul*Alive*PYR_Correct)*PYR_Weapon
- if(Shell_Exists==1){Shell:applyAngForce(WeaponTorque)} #Powers the shell (if present)
- else{Weapon:applyAngForce(WeaponTorque)} #Powers the weapon
- if(WeaponInput!=0){
- if(WeaponRPM<RPMCheck){
- ChassisTorque=(-WeaponInput*ChassisSpinPower*WeaponSpinMul*Alive*PYR_Correct)*PYR_Chassis*WPD_Mul*ShellMul*1.5
- Chassis:applyAngForce(ChassisTorque)} #Powers the chassis
- else{
- ChassisTorque=(-WeaponInput*SpinPower*WeaponSpinMul*Alive*PYR_Correct)*PYR_Chassis*WPD_Mul*CounterTorqueMul*0.5/SpinPowerMul
- Chassis:applyAngForce(ChassisTorque)} #Powers the chassis
- }
- }
- #=====================
- #WPD Damage Code
- DamageMultiplier = GrindMul*InertiaDamageMultiplier*PitchRelative^2 #Scales weapon damage based on current RPM
- Weapon:setDamageMultiplier(DamageMultiplier)
- WeaponDamage=Weapon:getTotalEntityDamage()
- ChassisDamage=Chassis:getTotalEntityDamage()
- Support1Damage=Support1:getTotalEntityDamage()
- if(Support2_Exists==1){
- Support2Damage=Support2:getTotalEntityDamage()}
- if(SupportAxle_Exists==1){
- SupportAxleDamage=SupportAxle:getTotalEntityDamage()}
- if(WeaponDamage>WeaponMaxHealth){ #Weapon is at 40% health (Would normally explode)
- if(changed(WeaponDamage)){
- if(Shell_Exists==0){WPD_Mul=WPD_Mul*0.9,SmokeCheck=1} #Below MaxHealth, every hit reduces weapon power by 10%
- if(Shell_Exists==1|(WeaponDamage>(WeaponMaxHealth+5000))) #After 5000 more damage, weapon comes off (If shell, teeth break)
- {
- Weapon:constraintBreak("axis")
- Weapon:constraintBreak("ballsocket")
- Weapon:constraintBreak("weld")
- Weapon:constraintBreak("rope")
- Weapon:constraintBreak("AdvBallsocket")
- Weapon:constraintBreak("advballsocket")
- Weapon:setDamagePropHealth(WeaponMaxHealth)
- }
- }
- }
- if(ChassisDamage>ChassisMaxHealth){ #Below MaxHealth, every hit reduces weapon power by 25%
- if(changed(ChassisDamage)){
- if(Chassis:getEntityDamage()>DamageThreshold){
- WPD_Mul=WPD_Mul*0.75,SmokeCheck=1}}
- }
- if(Support1Damage>Support1MaxHealth){ #Support1 is at 40% health (Would normally explode)
- if(changed(Support1Damage)){
- Support1Hits=Support1Hits+1
- if(Support1Hits==1){WPD_Mul=WPD_Mul*0.5,SmokeCheck=1} #First hit halves weapon power
- if(Support1Hits==2){WPD_Mul=0} #Second hit kills weapon power
- if(Support1Hits>2&(Support1:getEntityDamage())>DamageThreshold) #Third hit breaks support if above threshold
- {
- Support1:constraintBreak("axis")
- Support1:constraintBreak("ballsocket")
- Support1:constraintBreak("weld")
- Support1:constraintBreak("rope")
- Support1:constraintBreak("advballsocket")
- Support1:constraintBreak("AdvBallsocket")
- Support1:setDamagePropHealth(Support1MaxHealth)
- }
- }
- }
- if(Support2_Exists==1){
- if(Support2Damage>Support2MaxHealth){ #Support2 is at 40% health (Would normally explode)
- if(changed(Support2Damage)){
- Support2Hits=Support2Hits+1
- if(Support2Hits==1){WPD_Mul=WPD_Mul*0.5,SmokeCheck=1} #First hit halves weapon power
- if(Support2Hits==2){WPD_Mul=0} #Second hit kills weapon power
- if(Support2Hits>2&(Support2:getEntityDamage())>DamageThreshold) #Third hit breaks support if above threshold
- {
- Support2:constraintBreak("axis")
- Support2:constraintBreak("ballsocket")
- Support2:constraintBreak("weld")
- Support2:constraintBreak("rope")
- Support2:constraintBreak("advballsocket")
- Support2:constraintBreak("AdvBallsocket")
- Support2:setDamagePropHealth(Support2MaxHealth)
- }
- }
- }
- }
- if(SupportAxle_Exists==1){
- if(SupportAxleDamage>SupportAxleMaxHealth){ #SupportAxle is at 40% health (Would normally explode)
- if(changed(SupportAxleDamage)){
- SupportAxleHits=SupportAxleHits+1
- if(SupportAxleHits==1){WPD_Mul=WPD_Mul*0.5,SmokeCheck=1} #First hit halves weapon power
- if(SupportAxleHits==2){WPD_Mul=0.0} #Second hit kills weapon power
- if(SupportAxleHits>2&(SupportAxle:getEntityDamage())>DamageThreshold)#Third hit breaks support
- {
- SupportAxle:constraintBreak("axis")
- SupportAxle:constraintBreak("ballsocket")
- SupportAxle:constraintBreak("weld")
- SupportAxle:constraintBreak("rope")
- SupportAxle:constraintBreak("advballsocket")
- SupportAxle:constraintBreak("AdvBallsocket")
- SupportAxle:setDamagePropHealth(SupportAxleMaxHealth)
- }
- }
- }
- }
- #=====================
- #Smoke Code
- if(SmokeCheck==1){
- if(Smoke==1){timer("SmokeTimeOn",25)}
- if(Smoke==0){timer("SmokeTimeOff",150)}
- if(clk("SmokeTimeOn")){Smoke=0}
- if(clk("SmokeTimeOff")){Smoke=1}
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment