From 4e83b351a8581ec04cd7ecd54588514eb6207ba6 Mon Sep 17 00:00:00 2001 From: DBmaoha <56738369+DBmaoha@users.noreply.github.com> Date: Sat, 7 Jan 2023 04:42:13 +0800 Subject: [GAMEMODE] Add gamemode_fw (#545) * Initial commit Co-Authored-By: Ghroth-follower <45908037+Ghroth-follower@users.noreply.github.com> Co-Authored-By: zxcPandora <81985226+zxcPandora@users.noreply.github.com> * add customized scripts Co-Authored-By: Ghroth-follower <45908037+Ghroth-follower@users.noreply.github.com> Co-Authored-By: zxcPandora <81985226+zxcPandora@users.noreply.github.com> * add royal as co-worker Co-Authored-By: Maya <11448698+RoyalBlue1@users.noreply.github.com> * reset harvester.gnut * Update _gamemode_fw.nut * no need to update alertLevel right after clear * hacked natural turret receives less health * change consts name * update HACK_ForceDestroyNPCs() * update battery port's usePrompts * batteryPort useHint update * should do a check for titans * disable cloak while applying battery * add debounce for turret notifications * fix escalate * fix complex crash * late spawn camp trackers * defensive fix after havester destroyed * nerf salvo core and titan's earn meter * edit rodeo_titan in Northstar.Custom * make settings controllable by playlistvars * use tabs for indenting use tabs for indenting * Move game mode specific behaviour to callback use post damage callback * Move FW specific code out of _battery_port.gnut Also Split Damage Callbacks to onDamage and onPostDamage * Fix globalizing same function twice * Adding vars back to HarvesterStruct * use tabs for indenting use tabs for indenting Co-authored-by: Ghroth-follower <45908037+Ghroth-follower@users.noreply.github.com> Co-authored-by: zxcPandora <81985226+zxcPandora@users.noreply.github.com> Co-authored-by: Maya <11448698+RoyalBlue1@users.noreply.github.com> Co-authored-by: zxcPandora <1158500986@qq.com> --- .../mod/scripts/vscripts/_harvester.gnut | 3 + .../mod/scripts/vscripts/mp/_battery_port.gnut | 220 ++++++++++++++++++++- .../mod/scripts/vscripts/rodeo/_rodeo_titan.gnut | 9 +- .../mod/scripts/vscripts/sh_powerup.gnut | 4 +- .../vscripts/titan/_replacement_titans.gnut | 53 ++++- .../vscripts/titan/_replacement_titans_drop.gnut | 17 +- 6 files changed, 298 insertions(+), 8 deletions(-) (limited to 'Northstar.CustomServers/mod/scripts/vscripts') diff --git a/Northstar.CustomServers/mod/scripts/vscripts/_harvester.gnut b/Northstar.CustomServers/mod/scripts/vscripts/_harvester.gnut index f2776bdad..542db4d50 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/_harvester.gnut +++ b/Northstar.CustomServers/mod/scripts/vscripts/_harvester.gnut @@ -9,6 +9,9 @@ global struct HarvesterStruct { entity rings float lastDamage bool shieldBoost + bool harvesterShieldDown + float harvesterDamageTaken + bool havesterWasDamaged } diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/_battery_port.gnut b/Northstar.CustomServers/mod/scripts/vscripts/mp/_battery_port.gnut index 37b891699..ea88c1bce 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/mp/_battery_port.gnut +++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/_battery_port.gnut @@ -1 +1,219 @@ -//fuck \ No newline at end of file +untyped +global function InitTurretBatteryPort // only for fw turrets! + +void function InitTurretBatteryPort( entity batteryPort ) +{ + + batteryPort.s.beingUsed <- false // bool + batteryPort.s.hackAvaliable <- true // bool, for controlling hacking avaliablity + + // SetUsableByGroup() updates is done in TurretStateWatcher() + batteryPort.SetUsableByGroup( "pilot" ) // show hind to any pilots + batteryPort.SetUsePrompts( "#RODEO_APPLY_BATTERY_HINT", "#RODEO_APPLY_BATTERY_HINT" ) // don't know what to use + AddCallback_OnUseEntity( batteryPort, OnUseTurretBatteryPort ) +} + +function OnUseTurretBatteryPort( entBeingUse, user ) +{ + expect entity( entBeingUse ) + expect entity( user ) + + //print( "try to use batteryPort" ) + thread TryUseTurretBatteryPort( user, entBeingUse ) +} + +void function TryUseTurretBatteryPort( entity player, entity batteryPort ) +{ + if( batteryPort.s.beingUsed ) // already being using + return + + player.EndSignal( "OnDeath" ) + player.EndSignal( "OnDestroy" ) + player.EndSignal( "ScriptAnimStop" ) // so you can jump off animation + AddButtonPressedPlayerInputCallback( player, IN_JUMP, ForceStopUseBatteryPort ) + + OnThreadEnd( + function():( player ) + { + RemoveButtonPressedPlayerInputCallback( player, IN_JUMP, ForceStopUseBatteryPort ) + } + ) + + + var BatteryPortUsable = batteryPort.s.isUsable + + if( expect bool( BatteryPortUsable( batteryPort, player ) ) ) + { + // friendly try to apply one, or enemy try to hack this turret + waitthread PlayerApplesBatteryPackToPort( player, batteryPort ) + } +} + +void function ForceStopUseBatteryPort( entity player ) +{ + player.Signal( "ScriptAnimStop" ) +} + +void function PlayerApplesBatteryPackToPort( entity player, entity batteryPort ) +{ + table result = {} + result.success <- false + batteryPort.s.beingUsed = true + + BatteryPortSequenceStruct dataStruct = DisableCloakBeforeBatteryPortSequence( player ) + + // these are from _rodeo_titan.gnut + entity battery = GetBatteryOnBack( player ) + battery.Hide() //Hide it because the animation has a battery model already + Battery_StopFX( battery ) + + entity tempBattery3p + tempBattery3p = CreatePropDynamic( RODEO_BATTERY_MODEL_FOR_RODEO_ANIMS ) + tempBattery3p.SetParent( player, "R_HAND", false, 0.0 ) + tempBattery3p.RemoveFromSpatialPartition() + + entity tempBattery1p + tempBattery1p = CreatePropDynamic( RODEO_BATTERY_MODEL_FOR_RODEO_ANIMS ) + tempBattery1p.SetParent( player.GetFirstPersonProxy(), "R_HAND", false, 0.0 ) + tempBattery1p.RemoveFromSpatialPartition() + + player.p.rodeoAnimTempProps.append( tempBattery3p ) + player.p.rodeoAnimTempProps.append( tempBattery1p ) + + OnThreadEnd( + function() : ( battery, batteryPort, player, result, dataStruct ) + { + if ( IsValid( battery ) ) // animation interrupted, otherwise the battery will be destroyed + { + battery.Show() + Battery_StartFX( battery ) + } + + if ( IsValid( batteryPort ) ) + { + batteryPort.s.beingUsed = false + batteryPort.Anim_Stop() + } + + if ( IsValid( player ) ) + { + // restore control + DeployAndEnableWeapons( player ) + //ViewConeFree( player ) // no need to lock viewcone + + // clean up + ClearBatteryAnimTempProps( player ) + PutEntityInSafeSpot( player, player, null, player.GetOrigin() + <0, 0, 32>, player.GetOrigin() ) + + CleanUpBatterySequenceForPlayer( player ) + RestoreCloakAfterBatteryPortSequence( player, dataStruct ) + } + } + ) + + FirstPersonSequenceStruct sequence + sequence.attachment = "REF" // only ref the batteryPort has + + sequence.thirdPersonAnim = "pt_mp_battery_port_insert" //"pt_rodeo_ride_r_return_battery" + sequence.firstPersonAnim = "ptpov_mp_battery_port_insert" //"ptpov_rodeo_ride_r_return_battery" + + // player stats + HolsterAndDisableWeapons( player ) + //ViewConeZero( player ) // no need to lock viewcone + + batteryPort.Anim_Play( "bp_mp_battery_port_insert" ) + + thread WaitForActivateBattery( player, battery, batteryPort ) + waitthread FirstPersonSequence( sequence, player, batteryPort ) +} + +void function WaitForActivateBattery( entity player, entity battery, entity batteryPort ) +{ + player.EndSignal( "OnDeath" ) + player.EndSignal( "OnDestroy" ) + player.EndSignal( "ScriptAnimStop" ) // so you can jump off animation + battery.EndSignal( "OnDestroy" ) + + player.WaitSignal( "BatteryActivate" ) // this is registered in _gamemode_fw.nut! + ApplyBatteryToBatteryPort( player, batteryPort ) +} + +void function ApplyBatteryToBatteryPort( entity player, entity batteryPort ) +{ + if ( player.GetPlayerNetInt( "batteryCount" ) <= 0 ) // player actually not carrying a battery + return + + entity battery = Rodeo_TakeBatteryAwayFromPilot( player ) + if ( !IsValid( battery ) ) + return + + // player can apply battery + + // disable hacking + batteryPort.s.hackAvaliable = false // can't be hacked again until completely killed + + + var useBatteryPort = batteryPort.s.useBattery + useBatteryPort( batteryPort, player ) + + // all things done, destroy this batt + battery.Destroy() +} + +// for disabling cloak +struct BatteryPortSequenceStruct +{ + bool wasCloaked = false + float cloakEndTime = 0.0 +} + +BatteryPortSequenceStruct function DisableCloakBeforeBatteryPortSequence( entity player ) +{ + BatteryPortSequenceStruct dataStruct + if ( !IsCloaked( player ) ) + return dataStruct // empty struct! + + dataStruct.wasCloaked = true + dataStruct.cloakEndTime = player.GetCloakEndTime() + DisableCloak( player, 0.0 ) + + return dataStruct +} + +bool function RestoreCloakAfterBatteryPortSequence( entity player, BatteryPortSequenceStruct dataStruct ) +{ + if ( !IsAlive( player ) ) + return false + + if ( !dataStruct.wasCloaked ) + return false + + if ( dataStruct.cloakEndTime <= 0.0 ) + return false + + float remainingCloakDuration = max( 0.0, dataStruct.cloakEndTime - Time() ) + if ( remainingCloakDuration <= CLOAK_FADE_IN ) //Has to be greater than 1.0 fade in duration, otherwise will cloak forever + return false + + EnableCloak( player, remainingCloakDuration, CLOAK_FADE_IN ) + return true +} + +void function CleanUpBatterySequenceForPlayer( entity player ) +{ + ClearPlayerAnimViewEntity( player ) + player.AnimViewEntity_SetLerpOutTime( 0.4 ) // blend out the clear anim view entity + player.ClearParent() + player.Anim_Stop() +} + +void function ClearBatteryAnimTempProps( entity player ) +{ + foreach( tempProp in player.p.rodeoAnimTempProps ) + { + if ( IsValid( tempProp ) ) + tempProp.Destroy() + } + + player.p.rodeoAnimTempProps.clear() +} \ No newline at end of file diff --git a/Northstar.CustomServers/mod/scripts/vscripts/rodeo/_rodeo_titan.gnut b/Northstar.CustomServers/mod/scripts/vscripts/rodeo/_rodeo_titan.gnut index 9f05a0cd3..78cfdb27f 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/rodeo/_rodeo_titan.gnut +++ b/Northstar.CustomServers/mod/scripts/vscripts/rodeo/_rodeo_titan.gnut @@ -41,6 +41,9 @@ global function Battery_StopFXAndHideIconForPlayer global function RemovePlayerAirControl //This function should really be in a server only SP & MP utility script file. No such file exists as of right now. global function RestorePlayerAirControl //This function should really be in a server only SP & MP utility script file. No such file exists as of right now. +// needs these +global function Rodeo_TakeBatteryAwayFromPilot + #if DEV global function SetDebugRodeoPrint global function GetDebugRodeoPrint @@ -336,7 +339,7 @@ void function RodeoBatteryRemoval( entity pilot ) if ( !playerHadBattery ) { - AddPlayerScore( pilot, "PilotBatteryStolen" ) + AddPlayerScore( pilot, "PilotBatteryStolen", pilot ) entity battery = Rodeo_CreateBatteryPack( titan ) Rodeo_PilotPicksUpBattery( pilot, battery ) thread BatteryThiefHighlight( pilot ) @@ -1853,7 +1856,7 @@ void function Rodeo_OnTouchBatteryPack_Internal( entity player, entity batteryPa Battery_StopFX( batteryPack ) //Will be turned on again when player loses cloak Rodeo_PilotPicksUpBattery( player, batteryPack ) - AddPlayerScore( player, "PilotBatteryPickup" ) + AddPlayerScore( player, "PilotBatteryPickup", player ) // MessageToPlayer( player, eEventNotifications.Rodeo_PilotPickedUpBattery ) return } @@ -1878,7 +1881,7 @@ void function Rodeo_PilotAddsBatteryToFriendlyTitan( entity rider, entity titan Rodeo_ApplyBatteryToTitan( battery, titan ) //This destroys the battery - AddPlayerScore( rider, "PilotBatteryApplied" ) + AddPlayerScore( rider, "PilotBatteryApplied", rider ) EmitSoundOnEntityOnlyToPlayer( rider, rider, PILOT_APPLIES_BATTERY_TO_TITAN_HEALTH_RESTORED_SOUND ) diff --git a/Northstar.CustomServers/mod/scripts/vscripts/sh_powerup.gnut b/Northstar.CustomServers/mod/scripts/vscripts/sh_powerup.gnut index 75002e813..c390b5f57 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/sh_powerup.gnut +++ b/Northstar.CustomServers/mod/scripts/vscripts/sh_powerup.gnut @@ -79,7 +79,9 @@ bool function LTSShouldSpawnPowerUp() if ( HasIronRules() ) return false - return ( GAMETYPE == LAST_TITAN_STANDING || GAMETYPE == LTS_BOMB ) + // modified for fw + //return ( GAMETYPE == LAST_TITAN_STANDING || GAMETYPE == LTS_BOMB ) + return ( GAMETYPE == LAST_TITAN_STANDING || GAMETYPE == LTS_BOMB || GAMETYPE == FORT_WAR ) } bool function DefaultShouldSpawnPowerUp() diff --git a/Northstar.CustomServers/mod/scripts/vscripts/titan/_replacement_titans.gnut b/Northstar.CustomServers/mod/scripts/vscripts/titan/_replacement_titans.gnut index c9d986bcc..349f9131f 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/titan/_replacement_titans.gnut +++ b/Northstar.CustomServers/mod/scripts/vscripts/titan/_replacement_titans.gnut @@ -20,7 +20,7 @@ global function req global function ReplacementTitan global function TryAnnounceTitanfallWarningToEnemyTeam global function GetTitanForPlayer - +global function TryPlayTitanfallNegativeSoundToPlayer global function ShouldSetTitanRespawnTimer @@ -33,6 +33,7 @@ global function SetReplacementTitanGamemodeRules global function SetRequestTitanGamemodeRules global function CreateTitanForPlayerAndHotdrop +global function SetRequestTitanAllowedCallback struct { array ETATimeThresholds = [ 120, 60, 30, 15 ] @@ -53,6 +54,8 @@ struct { bool functionref( entity ) ReplacementTitanGamemodeRules bool functionref( entity, vector ) RequestTitanGamemodeRules + bool functionref( entity player, array< string > args ) RequestTitanAllowedCallback + } file const nagInterval = 40 @@ -87,6 +90,10 @@ function ReplacementTitans_Init() FlagInit( "LevelHasRoof" ) } +void function SetRequestTitanAllowedCallback( bool functionref( entity player, array args ) RequestTitanAllowedCallback ) +{ + file.RequestTitanAllowedCallback = RequestTitanAllowedCallback +} void function ReplacementTitan_InitPlayer( entity player ) { @@ -424,6 +431,7 @@ function TryETATitanReadyAnnouncement( entity player ) TryReplacementTitanReadyAnnouncement( player ) return } + //This entire loop is probably too complicated now for what it's doing. Simplify next game! //Loop might be pretty hard to read, a particular iteration of the loop is written in comments below @@ -524,10 +532,39 @@ function req() bool function ClientCommand_RequestTitan( entity player, array args ) { + if( file.RequestTitanAllowedCallback != null && !file.RequestTitanAllowedCallback( player, args ) ) + return true + ReplacementTitan( player ) //Separate function because other functions will call ReplacementTitan return true } +bool function TryPlayTitanfallNegativeSoundToPlayer( entity player ) +{ + if( !( "lastNegativeSound" in player.s ) ) + player.s.lastNegativeSound <- 0.0 // float + if( player.s.lastNegativeSound + 3.0 > Time() ) // in sound cooldown + return false + + EmitSoundOnEntityOnlyToPlayer( player, player, "titan_dryfire" ) + player.s.lastNegativeSound = Time() + + return true +} + +/* // serverSideRUI can't handle localized strings +void function CreateCustomMessageForRefusingTitanfall( entity player ) +{ + if( !( "lastMessageSend" in player.s ) ) + player.s.lastMessageSend <- 0.0 // float + if( player.s.lastMessageSend + 10 > Time() ) // in message cooldown + return + + NSSendInfoMessageToPlayer( player, "#FW_OBJECTIVE_TITANFALL" ) + player.s.lastMessageSend = Time() +} +*/ + // This a baseline titan request function; the only things that prevent this from happening are // common cases; wrong gamestate, already has a titan, is currently dead, etc... bool function RequestTitan( entity player ) @@ -877,6 +914,20 @@ void function CreateTitanForPlayerAndHotdrop( entity player, Point spawnPoint, T player.Signal( "titan_impact" ) thread TitanNPC_WaitForBubbleShield_StartAutoTitanBehavior( titan ) + thread PlayerEarnMeter_ReplacementTitanThink( player, titan ) +} + +void function PlayerEarnMeter_ReplacementTitanThink( entity player, entity titan ) +{ + player.EndSignal( "OnDestroy" ) + OnThreadEnd( + function(): ( player ) + { + if( IsValid( player ) ) + PlayerEarnMeter_Reset( player ) + } + ) + titan.WaitSignal( "OnDestroy" ) } void function CleanupTitanFallDisablingEntity( entity titanFallDisablingEntity, entity titan ) diff --git a/Northstar.CustomServers/mod/scripts/vscripts/titan/_replacement_titans_drop.gnut b/Northstar.CustomServers/mod/scripts/vscripts/titan/_replacement_titans_drop.gnut index 933e9988f..6972d5ff0 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/titan/_replacement_titans_drop.gnut +++ b/Northstar.CustomServers/mod/scripts/vscripts/titan/_replacement_titans_drop.gnut @@ -4,6 +4,7 @@ global function HullTraceDropPoint global function DebugTitanfall global function TitanFindDropNodes global function TitanHulldropSpawnpoint +global function SetRecalculateTitanReplacementPointCallback global const TITANDROP_LOS_DIST = 2000 // 2D distance at which we do the line of sight check to see where the player wants to call in the titan global const TITANDROP_MIN_FOV = 10 @@ -19,8 +20,15 @@ global const TITANDROP_FALLBACK_DIST = 150 // if the ground search hits, we go t struct { int replacementSpawnpointsID + Point functionref(Point originalPoint, entity player) recalculateTitanReplacementPointCallback } file + +void function SetRecalculateTitanReplacementPointCallback(Point functionref(Point originalPoint, entity player) recalculateTitanReplacementPointCallback) +{ + file.recalculateTitanReplacementPointCallback = recalculateTitanReplacementPointCallback +} + void function ReplacementTitansDrop_Init() { AddSpawnCallback( "info_spawnpoint_titan", AddDroppoint ) @@ -117,7 +125,10 @@ Point function GetTitanReplacementPoint( entity player, bool forDebugging = fals vector playerEyeAngles = player.EyeAngles() vector playerOrg = player.GetOrigin() - return CalculateTitanReplacementPoint( playerOrg, playerEyePos, playerEyeAngles, forDebugging ) + Point tempPoint = CalculateTitanReplacementPoint( playerOrg, playerEyePos, playerEyeAngles, forDebugging) + if( file.recalculateTitanReplacementPointCallback != null ) + tempPoint = file.recalculateTitanReplacementPointCallback( tempPoint, player ) + return tempPoint } Point function CalculateTitanReplacementPoint( vector playerOrg, vector playerEyePos, vector playerEyeAngles, bool forDebugging = false ) @@ -165,6 +176,7 @@ Point function CalculateTitanReplacementPoint( vector playerOrg, vector playerEy Point point point.origin = dropPoint point.angles = yawAngles + return point } } @@ -215,7 +227,8 @@ Point function CalculateTitanReplacementPoint( vector playerOrg, vector playerEy Point point point.origin = nodeOrigin point.angles = Vector( 0, yaw, 0 ) - return point + + return point } vector function GetPathNodeSearchPosWithLookPos( vector playerOrg, vector playerEyePos, vector playerEyeForward, vector playerLookPos, bool debug ) -- cgit v1.2.3