From 7ae27c1fbf43454fbe41a2dd8fe83491e24b4243 Mon Sep 17 00:00:00 2001 From: "theastropath@gmail.com" Date: Sat, 9 Mar 2024 23:59:54 -0500 Subject: [PATCH] Added Resident Evil Mode effect for Crowd Control. #645 --- DXRModules/DeusEx/Classes/DXRMachines.uc | 25 +++ DXRVanilla/DeusEx/Classes/Player.uc | 15 ++ DXRando.cs | 17 +- DXRando/DeusEx/Classes/CCResidentEvilCam.uc | 171 ++++++++++++++++++ .../Classes/DXRandoCrowdControlEffects.uc | 55 ++++++ .../DeusEx/Classes/DXRandoCrowdControlLink.uc | 3 +- 6 files changed, 278 insertions(+), 8 deletions(-) create mode 100644 DXRando/DeusEx/Classes/CCResidentEvilCam.uc diff --git a/DXRModules/DeusEx/Classes/DXRMachines.uc b/DXRModules/DeusEx/Classes/DXRMachines.uc index 840629f55..6409f6d36 100644 --- a/DXRModules/DeusEx/Classes/DXRMachines.uc +++ b/DXRModules/DeusEx/Classes/DXRMachines.uc @@ -243,6 +243,31 @@ function bool GetCameraLocation(out vector loc, out rotator rotation) return true; } +function bool GetLazyCameraLocation(out vector loc, int max_range) +{ + local LocationNormal locnorm, ceiling; + local FMinMax distrange; + locnorm.loc = loc; + distrange.min = 0.1; + distrange.max = 16*max_range; + + if( NearestCeiling(locnorm, distrange, 16) ) { + ceiling = locnorm; + } else { + if( ! NearestFloor(locnorm, distrange, 16) ) return false; + locnorm.loc.Z += 16*3; + ceiling = locnorm; + ceiling.loc.Z += 16*6; + } + distrange.max = 16*75; + if( ! NearestWallSearchZ(locnorm, distrange, 16*3, ceiling.loc, 10) ) return false; + + loc = locnorm.loc; + + return true; +} + + function bool MoveCamera(#var(prefix)SecurityCamera c, vector loc) { local rotator rotation; diff --git a/DXRVanilla/DeusEx/Classes/Player.uc b/DXRVanilla/DeusEx/Classes/Player.uc index 22479bcef..05734a58b 100644 --- a/DXRVanilla/DeusEx/Classes/Player.uc +++ b/DXRVanilla/DeusEx/Classes/Player.uc @@ -31,6 +31,21 @@ function PlayerMove( float DeltaTime ) GotoState('PlayerWalking'); } +event PlayerCalcView(out actor ViewActor, out vector CameraLocation, out rotator CameraRotation ) +{ + local CCResidentEvilCam reCam; + + reCam = CCResidentEvilCam(ViewTarget); + + if (reCam!=None){ + CameraRotation = reCam.Rotation; + CameraLocation = reCam.Location; + return; + } else { + Super.PlayerCalcView(ViewActor,CameraLocation,CameraRotation); + } +} + event ClientTravel( string URL, ETravelType TravelType, bool bItems ) { nextMap = URL; diff --git a/DXRando.cs b/DXRando.cs index bb6502c0f..6f4fcf48b 100644 --- a/DXRando.cs +++ b/DXRando.cs @@ -29,7 +29,6 @@ public DeusEx(UserRecord player, Func responseHandler, new Effect("Full Heal", "full_heal"){Price = 30,Description = "Fully heal the player"}, new Effect("Drunk Mode", "drunk_mode"){Price = 10,Description = "Let the player overindulge with some nice alcohol"}, new Effect("Drop Selected Item", "drop_selected_item"){Price = 2,Description = "Toss the currently held weapon out in front of the player"}, - new Effect("Enable Matrix Mode", "matrix"){Price = 5,Description = "Make the player see the code behind the game...",Duration=60}, new Effect("Give Player EMP Field", "emp_field"){Price = 25,Description = "Make all electronics around the player go haywire for 15 seconds!",Duration=15}, new Effect("Give Bioelectric Energy (x10)", "give_energy") { Quantity = 100,Price = 1,Description = "Top up the players battery by a bit" }, new Effect("Give Skill Points (x100)", "give_skillpoints") { Quantity = 1000,Price = 5,Description = "Give the player some skill points" }, //Updated text for second Crowd Control batch @@ -38,7 +37,6 @@ public DeusEx(UserRecord player, Func responseHandler, new Effect("Gotta Go Fast", "gotta_go_fast"){Price = 5,Description = "Make the player go extremely fast!",Duration=60}, new Effect("Slow Like Snail", "gotta_go_slow"){Price = 5,Description = "Make the player go very slow...",Duration=60}, new Effect("Ice Physics!","ice_physics"){Price = 10,Description = "Make the ground freeze up and become as slippery as a skating rink!",Duration=60}, - new Effect("Go Third-Person","third_person"){Price = 5,Description = "Change the game into a third person shooter for a minute!",Duration=60}, new Effect("Take Double Damage","dmg_double"){Price = 10,Description = "Make the player weaker so they take double damage!",Duration=60}, new Effect("Take Half Damage","dmg_half"){Price = 5,Description = "Make the player tougher so they take half damage!",Duration=60}, new Effect("Give Credits (x100)", "add_credits") { Quantity = 1000,Price = 2,Description = "Make it rain on the player and give them some spare cash!" }, //Updated for text second Crowd Control batch @@ -57,10 +55,6 @@ public DeusEx(UserRecord player, Func responseHandler, new Effect ("Earthquake","earthquake"){Price = 25,Description = "Set off a massive earthquake in the game!",Duration=30}, //New for fourth Crowd Control batch new Effect ("Full Bioelectric Energy","give_full_energy"){Price = 5,Description = "Completely fill the players bioelectric energy"}, //New for fourth Crowd Control batch new Effect ("Trigger all alarms","trigger_alarms"){Price = 5,Description = "Set off every alarm panel and security camera in the current level to make sure all the enemies are on high alert!"}, //New for fourth Crowd Control batch - new Effect ("Flip camera upside down","flipped"){Price = 20,Description = "Australia mode",Duration=60}, //New for fourth Crowd Control batch - new Effect ("Flip camera sideways","limp_neck"){Price = 20,Description = "Just turn the screen to the side!",Duration=60}, //New for fourth Crowd Control batch - new Effect ("Do a barrel roll!","barrel_roll"){Price = 25,Description = "The camera does an ever so slow barrel roll over the course of a minute...",Duration=60}, //New for fourth Crowd Control batch - new Effect ("Set off a Flashbang", "flashbang"){Price = 5,Description = "Set off a flashbang in the players face"}, //New for fourth Crowd Control batch new Effect ("Eat Beans", "eat_beans"){Price = 5,Description = "Force feed the player a bunch of beans and witness the consequences!",Duration=60}, //New for fourth Crowd Control batch new Effect ("Fire the current weapon", "fire_weapon"){Price = 5,Description = "Fire whatever weapon the player is holding!"}, //New for fourth Crowd Control batch new Effect ("Switch to next item", "next_item"){Price = 2,Description = "Switch to the next item in the players item belt"}, //New for fourth Crowd Control batch @@ -198,6 +192,15 @@ public DeusEx(UserRecord player, Func responseHandler, new Effect("Give Rockets", "give_ammorocket") { Quantity = 100, Category = "Give Ammo",Price = 10,Description = "Give the player some rockets" }, //New for second Crowd Control batch new Effect("Give WP Rockets", "give_ammorocketwp") { Quantity = 100, Category = "Give Ammo",Price = 15,Description = "Give the player some WP rockets" }, //New for second Crowd Control batch new Effect("Give Sabot Shells", "give_ammosabot") { Quantity = 100, Category = "Give Ammo",Price = 20,Description = "Give the player some Sabot shells" }, //New for second Crowd Control batch - new Effect("Give Shotgun Shells", "give_ammoshell") { Quantity = 100, Category = "Give Ammo",Price = 5,Description = "Give the player some shotgun shells" } //New for second Crowd Control batch + new Effect("Give Shotgun Shells", "give_ammoshell") { Quantity = 100, Category = "Give Ammo",Price = 5,Description = "Give the player some shotgun shells" }, //New for second Crowd Control batch + + //Camera Effects + new Effect ("Flip camera upside down","flipped"){Category = "Camera Effects",Price = 20,Description = "Australia mode",Duration=60}, //New for fourth Crowd Control batch + new Effect ("Flip camera sideways","limp_neck"){Category = "Camera Effects",Price = 20,Description = "Just turn the screen to the side!",Duration=60}, //New for fourth Crowd Control batch + new Effect ("Do a barrel roll!","barrel_roll"){Category = "Camera Effects",Price = 25,Description = "The camera does an ever so slow barrel roll over the course of a minute...",Duration=60}, //New for fourth Crowd Control batch + new Effect("Go Third-Person","third_person"){Category = "Camera Effects",Price = 5,Description = "Change the game into a third person shooter for a minute!",Duration=60}, + new Effect("Enable Matrix Mode", "matrix"){Category = "Camera Effects",Price = 5,Description = "Make the player see the code behind the game...",Duration=60}, + new Effect ("Set off a Flashbang", "flashbang"){Category = "Camera Effects",Price = 5,Description = "Set off a flashbang in the players face"}, //New for fourth Crowd Control batch + new Effect ("Resident Evil Mode", "resident_evil"){Category = "Camera Effects",Price = 20,Description = "Switch the game to fixed camera angles! Very spooky!"} //New for fifth Crowd Control batch }; } diff --git a/DXRando/DeusEx/Classes/CCResidentEvilCam.uc b/DXRando/DeusEx/Classes/CCResidentEvilCam.uc new file mode 100644 index 000000000..d79bdc4d3 --- /dev/null +++ b/DXRando/DeusEx/Classes/CCResidentEvilCam.uc @@ -0,0 +1,171 @@ +class CCResidentEvilCam extends SecurityCamera; + +var DeusExPlayer p; +var bool Reposition; + +struct LocationNormal { + var vector loc; + var vector norm; +}; +struct FMinMax { + var float min; + var float max; +}; + +function PostBeginPlay() +{ + Super.PostBeginPlay(); + + Reposition = False; +} + +function bool FindNewCameraPosition() +{ + local DXRMachines dxrm; + local Vector loc; + local Rotator rot; + local bool success; + + foreach AllActors(class'DXRMachines',dxrm){break;} + + if (dxrm==None){ + return false; + } + + success = False; + + loc = p.Location; + + success = dxrm.GetLazyCameraLocation(loc,cameraRange*0.75); + + if (success){ + SetLocation(loc); + rot = Rotator(p.Location - loc); + SetRotation(rot); + DesiredRotation = rot; + Reposition=False; + } + + return success; +} + +function BindPlayer(DeusExPlayer play) +{ + p = play; + p.ViewTarget = Self; + FindNewCameraPosition(); +} + +function Tick(float deltaTime) +{ + local float ang; + local Rotator rot; + local DeusExPlayer curplayer; + + Super(#var(prefix)HackableDevices).Tick(deltaTime); + + if (p==None){ + return; + } + + curTarget = None; + + //Prevent it from going into stasis + LastRenderTime = p.LastRendered(); + DistanceFromPlayer=0; + + playerCheckTimer += deltaTime; + + if (playerCheckTimer > 0.1) + { + playerCheckTimer = 0; + CheckPlayerVisibility(p); + } + + if (Reposition){ + //If not, find new location + FindNewCameraPosition(); + } + + // DEUS_EX AMSD For multiplayer + ReplicatedRotation = DesiredRotation; + + +} + +function CheckPlayerVisibility(DeusExPlayer player) +{ + local float yaw, pitch, dist; + local Actor hit; + local Vector HitLocation, HitNormal; + local Rotator rot; + + if (player == None) + return; + + Reposition=True; + dist = Abs(VSize(player.Location - Location)); + + foreach TraceActors(class'Actor',hit,HitLocation,HitNormal,player.Location,Location) + { + //Immediately reposition if you're on the far side of a wall or door + if (LevelInfo(hit)!=None || Mover(hit)!=None){ + break; + } + + //Aim the camera at the player + if (hit == player) + { + // figure out if we can see the player + rot = Rotator(player.Location - Location); + rot.Roll = 0; + yaw = (Abs(Rotation.Yaw - rot.Yaw)) % 65536; + pitch = (Abs(Rotation.Pitch - rot.Pitch)) % 65536; + + // center the angles around zero + if (yaw > 32767) + yaw -= 65536; + if (pitch > 32767) + pitch -= 65536; + + if (!((Abs(yaw) < cameraFOV) && (Abs(pitch) < cameraFOV))) + { + // rotate to face the player + DesiredRotation = rot; + } + Reposition = False; + break; + } + } + + // if the player is out of range + if (dist > cameraRange) + { + Reposition = True; + } +} + + +defaultproperties +{ + bHidden=true + bCollideActors=false + bCollideWorld=false + bBlockActors=false + bBlockPlayers=false + bProjTarget=false + CollisionHeight=1 + CollisionRadius=1 + bActive=True + bNoAlarm=True + bSwing=False + bTrackPlayer=True + bGameRelevant=True + bAlwaysRelevant=True + bAlwaysTick=True + bInvincible=True + bStasis=False + cameraRange=500 + RotationRate=(Pitch=40000,Yaw=40000) + AmbientSound=None +} diff --git a/DXRando/DeusEx/Classes/DXRandoCrowdControlEffects.uc b/DXRando/DeusEx/Classes/DXRandoCrowdControlEffects.uc index a3081dadf..63c9a0abc 100644 --- a/DXRando/DeusEx/Classes/DXRandoCrowdControlEffects.uc +++ b/DXRando/DeusEx/Classes/DXRandoCrowdControlEffects.uc @@ -41,6 +41,7 @@ const InvertMovementTimeDefault = 60; const EarthquakeTimeDefault = 30; const CameraRollTimeDefault = 60; const EatBeansTimeDefault = 60; +const ResidentEvilTimeDefault = 60; struct ZoneFriction { @@ -70,6 +71,8 @@ var DXRandoCrowdControlPawn CrowdControlPawns[3]; var transient AugEffectState AugEffectStates[32]; //Vanilla has a 25 array, but in case mods bump it up? var transient bool AugEffectStatesInit; +var transient CCResidentEvilCam reCam; + var transient bool HaveFlamethrower; var transient bool FlamethrowerInit; @@ -208,6 +211,22 @@ function PeriodicUpdates() Fart(); } + if (isTimerActive('cc_ResidentEvil')){ + if (reCam==None){ + SpawnRECam(); + } + + player().bCrosshairVisible=False; + } + if (decrementTimer('cc_ResidentEvil')) { + PlayerMessage("Everything feels less horrifying"); + player().ViewTarget=None; + player().bCrosshairVisible=True; + if (reCam!=None){ + reCam.Destroy(); + } + } + if (flashbangDuration>0){ flashbangDuration--; if (flashbangDuration==0){ @@ -477,6 +496,10 @@ function CleanupOnExit() { if (isTimerActive('cc_invertMovementTimer')) { invertMovementControls(); } + if (reCam!=None && player().ViewTarget==reCam){ + player().ViewTarget=None; + reCam.Destroy(); + } } @@ -568,6 +591,8 @@ function int getDefaultTimerTimeByName(name timerName) { return CameraRollTimeDefault; case 'cc_EatBeans': return EatBeansTimeDefault; + case 'cc_ResidentEvil': + return ResidentEvilTimeDefault; default: PlayerMessage("Unknown timer name "$timerName); @@ -621,6 +646,9 @@ function string getTimerLabelByName(name timerName) { return "Camera"; case 'cc_EatBeans': return "Beans"; + case 'cc_ResidentEvil': + return "Fixed Cam"; + default: PlayerMessage("Unknown timer name "$timerName); @@ -1705,6 +1733,12 @@ function bool HealAllEnemies(string viewer) return True; } +function SpawnRECam() +{ + reCam=Spawn(class'CCResidentEvilCam',,,player().Location); + reCam.BindPlayer(player()); +} + function SplitString(string src, string divider, out string parts[8]) { local int i, c; @@ -2321,7 +2355,28 @@ function int doCrowdControlEvent(string code, string param[5], string viewer, in return TempFail; } break; + case "resident_evil": + if (!#defined(vanilla)){ + //Changes in player class + PlayerMessage("Resident Evil effect unavailable in this mod"); + return NotAvail; + } + if (!InGame()) { + return TempFail; + } + if (isTimerActive('cc_RollTimer')) { + return TempFail; + } + if (isTimerActive('cc_ResidentEvil')) { + return TempFail; + } + //datastorage.SetConfig('cc_cameraRoll',16383, 3600*12); + PlayerMessage(viewer@"made your view a little bit more horrific"); + startNewTimer('cc_ResidentEvil',duration); + player().bCrosshairVisible = False; + SpawnRECam(); + return Success; default: return doCrowdControlEventWithPrefix(code, param, viewer, type, duration); } diff --git a/DXRando/DeusEx/Classes/DXRandoCrowdControlLink.uc b/DXRando/DeusEx/Classes/DXRandoCrowdControlLink.uc index a7cea3c48..094c00f50 100644 --- a/DXRando/DeusEx/Classes/DXRandoCrowdControlLink.uc +++ b/DXRando/DeusEx/Classes/DXRandoCrowdControlLink.uc @@ -135,7 +135,7 @@ function int RandomOfflineEffects() { viewer = "Simulated Crowd Control"; param[0] = "1"; - switch(Rand(89)) { + switch(Rand(90)) { case 0: if(Rand(2)==0){ return 0; } else { return ccEffects.doCrowdControlEvent("poison", param, viewer, 0, 0); } case 1: return ccEffects.doCrowdControlEvent("glass_legs", param, viewer, 0, 0); case 2: param[0] = string(Rand(20)); return ccEffects.doCrowdControlEvent("give_health", param, viewer, 0, 0); @@ -275,6 +275,7 @@ function int RandomOfflineEffects() { case 86: return ccEffects.doCrowdControlEvent("giveenemyweapon_weaponlaw", param, viewer, 0, 0); case 87: return ccEffects.doCrowdControlEvent("giveenemyweapon_weaponhideagun", param, viewer, 0, 0); case 88: return ccEffects.doCrowdControlEvent("heal_all_enemies", param, viewer, 0, 0); + case 89: return ccEffects.doCrowdControlEvent("resident_evil", param, viewer, 0, 0); } return 0;