Skip to content

Commit

Permalink
Add CheeringCrowds and StopPedAttacks options
Browse files Browse the repository at this point in the history
  • Loading branch information
oldnapalm committed Jun 19, 2021
1 parent 850b72d commit bb9623a
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 12 deletions.
117 changes: 110 additions & 7 deletions BicycleCity/BicycleCity.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Runtime.InteropServices;
using GTA;
using GTA.Math;
using GTA.Native;

namespace BicycleCity
Expand All @@ -12,7 +14,12 @@ public class BicycleCity : Script
bool aggressiveDrivers;
bool aggressiveCyclists;
bool cyclistsBreakLaws;
DateTime lastTime;
bool cheeringCrowds;
int cheeringCrowdsSlope;
bool stopPedAttacks;
DateTime lastTime = DateTime.UtcNow;
DateTime lastPaparazzi = DateTime.UtcNow;
List<Ped> fans = new List<Ped>();
string[] availableBicycles = { "BMX", "CRUISER", "FIXTER", "SCORCHER", "TRIBIKE", "TRIBIKE2", "TRIBIKE3" };
VehicleDrivingFlags aggressiveDrivingStyle = VehicleDrivingFlags.AvoidEmptyVehicles |
VehicleDrivingFlags.AvoidObjects |
Expand All @@ -29,23 +36,25 @@ public BicycleCity()
{
ScriptSettings settings = ScriptSettings.Load(@".\Scripts\BicycleCity.ini");
bikesPercentage = settings.GetValue("Main", "BikesPercentage", 50);
if (bikesPercentage > 100)
bikesPercentage = 100;
if (bikesPercentage < 0) bikesPercentage = 0;
if (bikesPercentage > 100) bikesPercentage = 100;
aggressiveDrivers = settings.GetValue("Main", "AggressiveDrivers", false);
aggressiveCyclists = settings.GetValue("Main", "AggressiveCyclists", false);
cyclistsBreakLaws = settings.GetValue("Main", "CyclistsBreakLaws", false);
lastTime = DateTime.UtcNow;
cheeringCrowds = settings.GetValue("Main", "CheeringCrowds", true);
cheeringCrowdsSlope = settings.GetValue("Main", "CheeringCrowdsSlope", 8);
stopPedAttacks = settings.GetValue("Main", "StopPedAttacks", false);
Tick += OnTick;
Aborted += OnAbort;
}

void OnTick(object sender, EventArgs e)
{
if (DateTime.UtcNow >= lastTime.AddSeconds(1))
{
Vehicle[] allVehicles = World.GetAllVehicles();
List<Vehicle> canChange = new List<Vehicle>();
int bicycles = 0;
foreach (Vehicle vehicle in allVehicles)
foreach (Vehicle vehicle in World.GetAllVehicles())
{
if (vehicle.Driver == null || vehicle.Driver.IsPlayer)
continue;
Expand All @@ -60,6 +69,7 @@ void OnTick(object sender, EventArgs e)
Function.Call(Hash.SET_DRIVE_TASK_DRIVING_STYLE, vehicle.Driver, (int)aggressiveDrivingStyle);
}
}
Random random = new Random();
int toChange = (bicycles + canChange.Count) * bikesPercentage / 100 - bicycles;
for (int i = 0; i < toChange; i++)
{
Expand All @@ -71,7 +81,6 @@ void OnTick(object sender, EventArgs e)
Function.Call(Hash.SET_ENTITY_AS_MISSION_ENTITY, driver, true, true);
driver.AlwaysKeepTask = false;
Model newModel;
Random random = new Random();
newModel = new Model(availableBicycles[random.Next(availableBicycles.Length)]);
newModel.Request();
if (newModel.IsInCdImage && newModel.IsValid)
Expand All @@ -98,8 +107,102 @@ void OnTick(object sender, EventArgs e)
}
}
canChange.Clear();

if (cheeringCrowds)
{
Vector3 point1 = Game.Player.Character.Position;
Vector3 point2 = Game.Player.Character.Position + Game.Player.Character.ForwardVector * 2f;
float slope = (World.GetGroundHeight(point2) - World.GetGroundHeight(point1)) / 2f;

if (slope > cheeringCrowdsSlope / 100f && fans.Count < 100)
{
NativeVector3 spawnPoint;
point2 = Game.Player.Character.ForwardVector;
unsafe
{
Function.Call(Hash.FIND_SPAWN_POINT_IN_DIRECTION, point1.X, point1.Y, point1.Z, point2.X, point2.Y, point2.Z, 100f, &spawnPoint);
}
var position = World.GetNextPositionOnSidewalk(spawnPoint);

if (DateTime.UtcNow >= lastPaparazzi.AddSeconds(10))
{
Model pModel;
pModel = new Model("a_m_m_paparazzi_01");
pModel.Request();
if (pModel.IsInCdImage && pModel.IsValid)
{
while (!pModel.IsLoaded)
Wait(10);
Ped paparazzi = World.CreatePed(pModel, position);
pModel.MarkAsNoLongerNeeded();
paparazzi.Task.StartScenario("WORLD_HUMAN_PAPARAZZI", 0f);
fans.Add(paparazzi);
}
lastPaparazzi = DateTime.UtcNow;
}
else
{
Ped fan = World.CreateRandomPed(position);
fan.Task.StartScenario("WORLD_HUMAN_CHEERING", 0f);
fans.Add(fan);
}
}

foreach (Ped fan in fans.ToArray())
{
if (fan != null)
{
if (fan.Position.DistanceTo(Game.Player.Character.Position) > 150f)
{
fan.Delete();
fans.Remove(fan);
}
}
else
fans.Remove(fan);
}
}

if (stopPedAttacks)
foreach (Ped ped in World.GetNearbyPeds(Game.Player.Character, 100f))
if ((ped.GetRelationshipWithPed(Game.Player.Character) == Relationship.Hate && ped.IsHuman) ||
ped.IsInCombat || ped.IsInMeleeCombat || ped.IsShooting)
{
ped.Delete();
}

lastTime = DateTime.UtcNow;
}

if (cheeringCrowds)
foreach (Ped fan in fans)
if (fan != null && !fan.IsRunning)
fan.Heading = (Game.Player.Character.Position - fan.Position).ToHeading();
}

void OnAbort(object sender, EventArgs e)
{
Tick -= OnTick;

if (cheeringCrowds)
{
foreach (Ped fan in fans)
fan.Delete();
fans.Clear();
}
}
}

[StructLayout(LayoutKind.Explicit, Size = 0x18)]
internal struct NativeVector3
{
[FieldOffset(0x00)]
internal float X;
[FieldOffset(0x08)]
internal float Y;
[FieldOffset(0x10)]
internal float Z;

public static implicit operator Vector3(NativeVector3 value) => new Vector3(value.X, value.Y, value.Z);
}
}
2 changes: 2 additions & 0 deletions BicycleCity/BicycleCity.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
Expand All @@ -29,6 +30,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<Reference Include="ScriptHookVDotNet3">
Expand Down
3 changes: 3 additions & 0 deletions BicycleCity/BicycleCity.ini
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@ BikesPercentage=50
AggressiveDrivers=false
AggressiveCyclists=false
CyclistsBreakLaws=false
CheeringCrowds=true
CheeringCrowdsSlope=8
StopPedAttacks=false
13 changes: 8 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@ Replace cars by bikes (GTA V mod)

## Installation
- Put `BicycleCity.dll` and `BicycleCity.ini` in the `Scripts` folder
- Optionally, edit `BicycleCity.ini`
- Change `BikesPercentage` if you want more or less cars replaced by bikes
- Set `AggressiveDrivers` to `true` if you want drivers to overtake slower vehicles
- Set `AggressiveCyclists` to `true` if you want cyclists to overtake slower vehicles
- Set `CyclistsBreakLaws` to `true` if you want cyclists to break traffic laws
- Optionally, open `BicycleCity.ini` and edit preferences
- **BikesPercentage** - percentage of cars replaced by bikes
- **AggressiveDrivers** - drivers will overtake slower vehicles
- **AggressiveCyclists** - cyclists will overtake slower vehicles
- **CyclistsBreakLaws** - cyclists will break traffic laws
- **CheeringCrowds** - cheering peds will be spawned on climbs
- **CheeringCrowdsSlope** - minimum slope for cheering crowds
- **StopPedAttacks** - attacking peds will be removed

## Download
https://github.com/oldnapalm/BicycleCity/releases/latest
Expand Down

0 comments on commit bb9623a

Please sign in to comment.