18 Commits

Author SHA1 Message Date
85706518fe Update to SHVDN nightly (#70) 2024-06-30 16:17:35 +08:00
49208371d1 Allow keyboard layout change in chat 2023-12-12 11:52:20 -03:00
761156a574 Avoid vehicle door break and repair loop 2023-11-27 10:24:35 -03:00
8bd6ea15a3 Remove global limits
world limits will be applied to all players instead
Fix explosions when remote and local vehicles exist at same position
Fix "floating corpses" issue when remote NPCs are killed
2023-11-20 11:32:18 -03:00
3c7f16f7a4 Add ped limit menu setting
Fix vehicle limit menu setting
Fix player blip disappearing after switching character
2023-11-12 10:50:37 -03:00
393a401860 Always sync vehicles with synced peds 2023-11-07 20:27:14 -03:00
4a54851c51 Update AssemblyInfo.cs 2023-10-23 10:36:57 -03:00
f0eefa575c Always sync player ped 2023-10-22 18:59:19 -03:00
3fc813b2d8 Fix bug disconnecting from server 2023-10-22 17:14:50 -03:00
fbff72ff14 Update LemonUI 2023-10-18 16:57:19 -03:00
4e52407591 Update nightly-build.yaml 2023-10-18 16:56:44 -03:00
4e6fde129d Add global limits 2023-10-18 10:41:34 -03:00
92e1a970a8 Show kill notification 2023-10-06 23:46:08 -03:00
d0eb0b7818 Bump version
Add kill message
2023-10-06 16:36:49 -03:00
14151d7b2c Add option to disable blip and nametag display 2023-08-14 14:08:30 -03:00
1f8d70a520 Fix player dying when switching characters in missions 2023-08-13 19:29:48 -03:00
2cb5baf5f7 Fix player dying when switching characters 2023-08-09 23:50:47 -03:00
9287aba0f9 Update README.md 2023-07-26 15:42:08 -03:00
33 changed files with 196 additions and 160 deletions

View File

@ -28,8 +28,6 @@ jobs:
run: dotnet publish RageCoop.Server/RageCoop.Server.csproj --self-contained -p:PublishSingleFile=true -p:PublishTrimmed=false -r win-x64 -o bin/Release/Server/win-x64 -c Release
- name: Build server linux-x64
run: dotnet publish RageCoop.Server/RageCoop.Server.csproj --self-contained -p:PublishSingleFile=true -p:PublishTrimmed=false -r linux-x64 -o bin/Release/Server/linux-x64 -c Release
- name: Build server linux-arm
run: dotnet publish RageCoop.Server/RageCoop.Server.csproj --self-contained -p:PublishSingleFile=true -p:PublishTrimmed=false -r linux-arm -o bin/Release/Server/linux-arm -c Release
- uses: vimtor/action-zip@v1
with:
files: bin/Release/Client
@ -45,11 +43,6 @@ jobs:
files: bin/Release/Server/linux-x64
dest: RageCoop.Server-linux-x64.zip
- uses: vimtor/action-zip@v1
with:
files: bin/Release/Server/linux-arm
dest: RageCoop.Server-linux-arm.zip
- uses: WebFreak001/deploy-nightly@v1.1.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # automatically provided by github actions
@ -82,17 +75,3 @@ jobs:
asset_name: RageCoop.Server-linux-x64.zip
asset_content_type: application/zip
max_releases: 7
- uses: WebFreak001/deploy-nightly@v1.1.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # automatically provided by github actions
with:
upload_url: https://uploads.github.com/repos/RAGECOOP/RAGECOOP-V/releases/70603992/assets{?name,label}
release_id: 70603992
asset_path: RageCoop.Server-linux-arm.zip
asset_name: RageCoop.Server-linux-arm.zip
asset_content_type: application/zip
max_releases: 7
- uses: actions/checkout@v2

View File

@ -15,7 +15,7 @@ RAGECOOP brings multiplayer experience to the story mode, you can complete missi
# 👁 Requirements
- ScriptHookV
- ScriptHookVDotNet 3.5.1 or later
- ScriptHookVDotNet 3.6.0 or later
- .NET Framework 4.8 Runtime or SDK
# 📋 Building the project
@ -49,7 +49,7 @@ Then run `dotnet build` in the solution directory, built binaries are in the `bi
5. Decent compatibility with other mods, set up a private modded server to have some fun!
6. Weaponized vehicle sync(WIP).
7. Optimization for high-Ping condition, play with friends around the world!
8. Powerful scripting API and resource system, easily [add multiplayer functionality to your mod](HTTPS://docs.ragecoop.online).
8. Powerful scripting API and resource system, easily [add multiplayer functionality to your mod](HTTPS://docs.ragecoop.com).
# ⚠ Known issues

View File

@ -43,7 +43,7 @@ namespace RageCoop.Client
public static void ShowTimeStamps()
{
GTA.UI.Notification.Hide(_lastNfHandle);
_lastNfHandle = GTA.UI.Notification.Show(Debug.TimeStamps.Dump());
_lastNfHandle = GTA.UI.Notification.PostTicker(TimeStamps.Dump(), false).Handle;
}
}

View File

@ -162,7 +162,7 @@ namespace RageCoop.Client
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
thread.Join();
GTA.UI.Notification.Show("Copied to clipboard, please paste it on the GitHub issue page!");
GTA.UI.Notification.PostTicker("Copied to clipboard, please paste it on the GitHub issue page!", false);
}
}

View File

@ -53,7 +53,7 @@ namespace RageCoop.Client
}
catch
{
GTA.UI.Notification.Show("Malformed configuration, overwriting with default values...");
GTA.UI.Notification.PostTicker("Malformed configuration, overwriting with default values...", false);
Settings = new Settings();
Util.SaveSettings();
}
@ -79,7 +79,7 @@ namespace RageCoop.Client
}
if (!_gameLoaded)
{
GTA.UI.Notification.Show("~r~Please update your GTA5 to v1.0.1290 or newer!", true);
GTA.UI.Notification.PostTicker("~r~Please update your GTA5 to v1.0.1290 or newer!", true);
_gameLoaded = true;
}
};
@ -117,7 +117,7 @@ namespace RageCoop.Client
else if (!_gameLoaded && (_gameLoaded = true))
{
#if !NON_INTERACTIVE
GTA.UI.Notification.Show(GTA.UI.NotificationIcon.AllPlayersConf, "RAGECOOP", "Welcome!", $"Press ~g~{Main.Settings.MenuKey}~s~ to open the menu.");
GTA.UI.Notification.PostMessageText($"Press ~g~{Settings.MenuKey}~s~ to open the menu.", new GTA.Graphics.TextureAsset("CHAR_ALL_PLAYERS_CONF", "CHAR_ALL_PLAYERS_CONF"), false, GTA.UI.FeedTextIcon.Message, "RAGECOOP", "Welcome!");
#endif
}
@ -170,7 +170,7 @@ namespace RageCoop.Client
P.Health = 1;
Game.Player.WantedLevel = 0;
Main.Logger.Debug("Player died.");
Scripting.API.Events.InvokePlayerDied();
Scripting.API.Events.InvokePlayerDied(KillMessage());
}
GTA.UI.Screen.StopEffects();
}
@ -181,7 +181,7 @@ namespace RageCoop.Client
}
else if (P.IsDead && !_lastDead)
{
Scripting.API.Events.InvokePlayerDied();
Scripting.API.Events.InvokePlayerDied(KillMessage());
}
_lastDead = P.IsDead;
@ -304,7 +304,7 @@ namespace RageCoop.Client
Function.Call(Hash.SET_ENABLE_VEHICLE_SLIPSTREAMING, true);
CoopMenu.ConnectedMenuSetting();
MainChat.Init();
GTA.UI.Notification.Show("~g~Connected!");
GTA.UI.Notification.PostTicker("~g~Connected!", false);
});
Logger.Info(">> Connected <<");
@ -326,7 +326,8 @@ namespace RageCoop.Client
WorldThread.Traffic(true);
Function.Call(Hash.SET_ENABLE_VEHICLE_SLIPSTREAMING, false);
CoopMenu.DisconnectedMenuSetting();
GTA.UI.Notification.Show("~r~Disconnected: " + reason);
if (reason != "Abort")
GTA.UI.Notification.PostTicker("~r~Disconnected: " + reason, false);
LocalPlayerID = default;
});
Memory.RestorePatches();
@ -393,5 +394,15 @@ namespace RageCoop.Client
});
}
private string KillMessage()
{
if (P.Killer != null)
{
var killer = EntityPool.GetPedByHandle(P.Killer.Handle);
if (killer != null && killer.ID == killer.Owner.ID)
return $"~h~{PlayerList.GetPlayer(LocalPlayerID).Username}~h~ was killed by ~h~{killer.Owner.Username}~h~ ({P.CauseOfDeath})";
}
return $"~h~{PlayerList.GetPlayer(LocalPlayerID).Username}~h~ died";
}
}
}

View File

@ -50,7 +50,7 @@ namespace RageCoop.Client.Menus
{
Menu.Banner.Color = Color.FromArgb(225, 0, 0, 0);
Menu.Title.Color = Color.FromArgb(255, 165, 0);
Menu.BannerText.Color = Color.FromArgb(255, 165, 0);
_usernameItem.Activated += UsernameActivated;
_passwordItem.Activated += _passwordActivated;
@ -99,7 +99,7 @@ namespace RageCoop.Client.Menus
Game.DisableAllControlsThisFrame();
MenuPool.Process();
var scaleform = new Scaleform("instructional_buttons");
var scaleform = Scaleform.RequestMovie("instructional_buttons");
scaleform.CallFunction("CLEAR_ALL");
scaleform.CallFunction("TOGGLE_MOUSE_BUTTONS", 0);
scaleform.CallFunction("CREATE_CONTAINER");

View File

@ -25,7 +25,7 @@ namespace RageCoop.Client
static DebugMenu()
{
Menu.Banner.Color = Color.FromArgb(225, 0, 0, 0);
Menu.Title.Color = Color.FromArgb(255, 165, 0);
Menu.BannerText.Color = Color.FromArgb(255, 165, 0);
DiagnosticMenu.Opening += (sender, e) =>

View File

@ -22,7 +22,7 @@ namespace RageCoop.Client
static DevToolMenu()
{
Menu.Banner.Color = Color.FromArgb(225, 0, 0, 0);
Menu.Title.Color = Color.FromArgb(255, 165, 0);
Menu.BannerText.Color = Color.FromArgb(255, 165, 0);
enableItem.Activated += enableItem_Activated;
enableItem.Checked = false;

View File

@ -30,7 +30,7 @@ namespace RageCoop.Client.Menus
static ServersMenu()
{
Menu.Banner.Color = Color.FromArgb(225, 0, 0, 0);
Menu.Title.Color = Color.FromArgb(255, 165, 0);
Menu.BannerText.Color = Color.FromArgb(255, 165, 0);
Menu.Opening += (object sender, System.ComponentModel.CancelEventArgs e) =>
{
@ -76,7 +76,7 @@ namespace RageCoop.Client.Menus
foreach (ServerInfo server in serverList)
{
string address = $"{server.address}:{server.port}";
NativeItem tmpItem = new NativeItem($"[{server.country}] {server.name}", $"~b~{address}~s~~n~~g~Version {server.version}.x~s~") { AltTitle = $"[{server.players}/{server.maxPlayers}]" };
NativeItem tmpItem = new NativeItem($"[{server.country}] {server.name}", $"~b~{address}~s~~n~~g~Version {server.version}~s~") { AltTitle = $"[{server.players}/{server.maxPlayers}]" };
tmpItem.Activated += (object sender, EventArgs e) =>
{
try
@ -85,7 +85,7 @@ namespace RageCoop.Client.Menus
if (server.useZT)
{
address = $"{server.ztAddress}:{server.port}";
Notification.Show($"~y~Joining ZeroTier network... {server.ztID}");
Notification.PostTicker($"~y~Joining ZeroTier network... {server.ztID}", false);
if (ZeroTierHelper.Join(server.ztID) == null)
{
throw new Exception("Failed to obtain ZeroTier network IP");
@ -102,10 +102,10 @@ namespace RageCoop.Client.Menus
}
catch (Exception ex)
{
Notification.Show($"~r~{ex.Message}");
Notification.PostTicker($"~r~{ex.Message}", false);
if (server.useZT)
{
Notification.Show($"Make sure ZeroTier is correctly installed, download it from https://www.zerotier.com/");
Notification.PostTicker($"Make sure ZeroTier is correctly installed, download it from https://www.zerotier.com/", false);
}
}
};

View File

@ -17,16 +17,19 @@ namespace RageCoop.Client.Menus
private static readonly NativeCheckboxItem _disableTrafficItem = new NativeCheckboxItem("Disable Traffic (NPCs/Vehicles)", "Local traffic only", Main.Settings.DisableTraffic);
private static readonly NativeCheckboxItem _flipMenuItem = new NativeCheckboxItem("Flip menu", Main.Settings.FlipMenu);
private static readonly NativeCheckboxItem _disablePauseAlt = new NativeCheckboxItem("Disable Alternate Pause", "Don't freeze game time when Esc pressed", Main.Settings.DisableAlternatePause);
private static readonly NativeCheckboxItem _showBlip = new NativeCheckboxItem("Show player blip", "Show other player's blip on map", Main.Settings.ShowPlayerBlip);
private static readonly NativeCheckboxItem _showNametag = new NativeCheckboxItem("Show player nametag", "Show other player's nametag on your screen", Main.Settings.ShowPlayerNameTag);
private static readonly NativeCheckboxItem _disableVoice = new NativeCheckboxItem("Enable voice", "Check your GTA:V settings to find the right key on your keyboard for PushToTalk and talk to your friends", Main.Settings.Voice);
private static readonly NativeItem _menuKey = new NativeItem("Menu Key", "The key to open menu", Main.Settings.MenuKey.ToString());
private static readonly NativeItem _passengerKey = new NativeItem("Passenger Key", "The key to enter a vehicle as passenger", Main.Settings.PassengerKey.ToString());
private static readonly NativeItem _vehicleSoftLimit = new NativeItem("Vehicle limit (soft)", "The game won't spawn more NPC traffic if the limit is exceeded. \n-1 for unlimited (not recommended).", Main.Settings.WorldVehicleSoftLimit.ToString());
private static readonly NativeItem _pedSoftLimit = new NativeItem("Ped limit (soft)", "The game won't spawn more NPCs if the limit is exceeded. \n-1 for unlimited (not recommended).", Main.Settings.WorldPedSoftLimit.ToString());
static SettingsMenu()
{
Menu.Banner.Color = Color.FromArgb(225, 0, 0, 0);
Menu.Title.Color = Color.FromArgb(255, 165, 0);
Menu.BannerText.Color = Color.FromArgb(255, 165, 0);
_disableTrafficItem.CheckboxChanged += DisableTrafficCheckboxChanged;
_disablePauseAlt.CheckboxChanged += DisablePauseAltCheckboxChanged;
@ -35,6 +38,17 @@ namespace RageCoop.Client.Menus
_menuKey.Activated += ChaneMenuKey;
_passengerKey.Activated += ChangePassengerKey;
_vehicleSoftLimit.Activated += VehicleSoftLimitActivated;
_pedSoftLimit.Activated += PedSoftLimitActivated;
_showBlip.Activated += (s, e) =>
{
Main.Settings.ShowPlayerBlip = _showBlip.Checked;
Util.SaveSettings();
};
_showNametag.Activated += (s, e) =>
{
Main.Settings.ShowPlayerNameTag = _showNametag.Checked;
Util.SaveSettings();
};
Menu.Add(_disableTrafficItem);
Menu.Add(_disablePauseAlt);
@ -43,6 +57,9 @@ namespace RageCoop.Client.Menus
Menu.Add(_menuKey);
Menu.Add(_passengerKey);
Menu.Add(_vehicleSoftLimit);
Menu.Add(_pedSoftLimit);
Menu.Add(_showBlip);
Menu.Add(_showNametag);
}
private static void DisableVoiceCheckboxChanged(object sender, EventArgs e)
@ -75,7 +92,19 @@ namespace RageCoop.Client.Menus
Main.Settings.WorldVehicleSoftLimit = int.Parse(
Game.GetUserInput(WindowTitle.EnterMessage20,
Main.Settings.WorldVehicleSoftLimit.ToString(), 20));
_menuKey.AltTitle = Main.Settings.WorldVehicleSoftLimit.ToString();
_vehicleSoftLimit.AltTitle = Main.Settings.WorldVehicleSoftLimit.ToString();
Util.SaveSettings();
}
catch { }
}
private static void PedSoftLimitActivated(object sender, EventArgs e)
{
try
{
Main.Settings.WorldPedSoftLimit = int.Parse(
Game.GetUserInput(WindowTitle.EnterMessage20,
Main.Settings.WorldPedSoftLimit.ToString(), 20));
_pedSoftLimit.AltTitle = Main.Settings.WorldPedSoftLimit.ToString();
Util.SaveSettings();
}
catch { }

View File

@ -31,6 +31,7 @@ namespace RageCoop.Client
}
private ulong LastMessageTime { get; set; }
private Keys LastKey { get; set; }
private bool CurrentHidden { get; set; }
private bool Hidden
@ -56,7 +57,7 @@ namespace RageCoop.Client
public Chat()
{
MainScaleForm = new Scaleform("multiplayer_chat");
MainScaleForm = Scaleform.RequestMovie("multiplayer_chat");
}
public void Init()
@ -115,6 +116,10 @@ namespace RageCoop.Client
MainScaleForm.CallFunction("PAGE_DOWN");
}
if (key == Keys.Menu && LastKey == Keys.ShiftKey)
ActivateKeyboardLayout(1, 0);
LastKey = key;
string keyChar = GetCharFromKey(key, Game.IsKeyPressed(Keys.ShiftKey), false);
if (keyChar.Length == 0)
@ -174,5 +179,8 @@ namespace RageCoop.Client
ToUnicodeEx((uint)key, 0, keyboardState, buf, 256, 0, InputLanguage.CurrentInputLanguage.Handle);
return buf.ToString();
}
[DllImport("user32.dll")]
public static extern int ActivateKeyboardLayout(int hkl, uint flags);
}
}

View File

@ -30,16 +30,16 @@ namespace RageCoop.Client
public static void ToggleConnection(string address, string username = null, string password = null, PublicKey publicKey = null)
{
Menus.CoopMenu.Menu.Visible = false;
Peer?.Shutdown("Bye");
if (IsOnServer)
{
// ?
}
else if (IsConnecting)
if (IsConnecting)
{
_publicKeyReceived.Set();
IsConnecting = false;
Notification.Show("Connection has been canceled");
Main.QueueAction(() => Notification.PostTicker("Connection has been canceled", false));
Peer?.Shutdown("Bye");
}
else if (IsOnServer)
{
Peer?.Shutdown("Bye");
}
else
{
@ -104,7 +104,7 @@ namespace RageCoop.Client
#endif
}
};
Main.QueueAction(() => { Notification.Show($"~y~Trying to connect..."); });
Main.QueueAction(() => { Notification.PostTicker($"~y~Trying to connect...", false); });
Menus.CoopMenu._serverConnectItem.Enabled = false;
Security.Regen();
if (publicKey == null)
@ -139,7 +139,7 @@ namespace RageCoop.Client
catch (Exception ex)
{
Main.Logger.Error("Cannot connect to server: ", ex);
Main.QueueAction(() => Notification.Show("Cannot connect to server: " + ex.Message));
Main.QueueAction(() => Notification.PostTicker("Cannot connect to server: " + ex.Message, false));
}
IsConnecting = false;
});
@ -159,7 +159,7 @@ namespace RageCoop.Client
Main.Logger.Debug($"player connected:{p.Username}");
Main.QueueAction(() =>
GTA.UI.Notification.Show($"~h~{p.Username}~h~ connected."));
Notification.PostTicker($"~h~{p.Username}~h~ connected.", false));
}
private static void PlayerDisconnect(Packets.PlayerDisconnect packet)
{
@ -169,7 +169,7 @@ namespace RageCoop.Client
Main.QueueAction(() =>
{
EntityPool.RemoveAllFromPlayer(packet.PedID);
GTA.UI.Notification.Show($"~h~{player.Username}~h~ left.");
Notification.PostTicker($"~h~{player.Username}~h~ left.", false);
});
}

View File

@ -3,6 +3,7 @@ using Lidgren.Network;
using RageCoop.Client.Menus;
using RageCoop.Core;
using System;
using System.Linq;
using System.Threading;
namespace RageCoop.Client
@ -159,6 +160,7 @@ namespace RageCoop.Client
Main.Logger.Error(ex);
Peer.Shutdown($"Packet Error [{packetType}]");
#endif
_recycle = false;
}
break;
}
@ -293,7 +295,7 @@ namespace RageCoop.Client
{
recycle = false;
// Dispatch to script thread
Main.QueueAction(() => { SyncEvents.HandleEvent(packetType, msg); Peer.Recycle(msg); return true; });
Main.QueueAction(() => { SyncEvents.HandleEvent(packetType, msg); return true; });
}
break;
}
@ -304,10 +306,15 @@ namespace RageCoop.Client
SyncedPed c = EntityPool.GetPedByID(packet.ID);
if (c == null)
{
// Main.Logger.Debug($"Creating character for incoming sync:{packet.ID}");
EntityPool.ThreadSafe.Add(c = new SyncedPed(packet.ID));
if (EntityPool.PedsByID.Count(x => x.Value.OwnerID == packet.OwnerID) < Main.Settings.WorldPedSoftLimit / PlayerList.Players.Count ||
/*EntityPool.VehiclesByID.Any(x => x.Value.Position.DistanceTo(packet.Position) < 2) ||*/ // allows players to exceed the peds limit
packet.ID == packet.OwnerID)
{
// Main.Logger.Debug($"Creating character for incoming sync:{packet.ID}");
EntityPool.ThreadSafe.Add(c = new SyncedPed(packet.ID));
}
else return;
}
PedDataFlags flags = packet.Flags;
c.ID = packet.ID;
c.OwnerID = packet.OwnerID;
c.Health = packet.Health;
@ -353,7 +360,13 @@ namespace RageCoop.Client
SyncedVehicle v = EntityPool.GetVehicleByID(packet.ID);
if (v == null)
{
EntityPool.ThreadSafe.Add(v = new SyncedVehicle(packet.ID));
if (EntityPool.VehiclesByID.Count(x => x.Value.OwnerID == packet.OwnerID) < Main.Settings.WorldVehicleSoftLimit / PlayerList.Players.Count ||
EntityPool.PedsByID.Any(x => x.Value.VehicleID == packet.ID || x.Value.Position.DistanceTo(packet.Position) < 2))
{
// Main.Logger.Debug($"Creating vehicle for incoming sync:{packet.ID}");
EntityPool.ThreadSafe.Add(v = new SyncedVehicle(packet.ID));
}
else return;
}
if (v.IsLocal) { return; }
v.ID = packet.ID;
@ -387,7 +400,6 @@ namespace RageCoop.Client
}
private static void ProjectileSync(Packets.ProjectileSync packet)
{
var p = EntityPool.GetProjectileByID(packet.ID);
if (p == null)
{

View File

@ -126,7 +126,7 @@ namespace RageCoop.Client
packet.Position = veh.ReadPosition();
packet.Velocity = veh.Velocity;
packet.Quaternion = veh.ReadQuaternion();
packet.RotationVelocity = veh.RotationVelocity;
packet.RotationVelocity = veh.LocalRotationVelocity;
packet.ThrottlePower = veh.ThrottlePower;
packet.BrakePower = veh.BrakePower;
v.LastSentStopWatch.Restart();

View File

@ -13,7 +13,7 @@ namespace RageCoop.Client
{
private const float LEFT_POSITION = 0.122f;
private const float RIGHT_POSITION = 0.9f;
private static readonly Scaleform _mainScaleform = new Scaleform("mp_mm_card_freemode");
private static readonly Scaleform _mainScaleform = Scaleform.RequestMovie("mp_mm_card_freemode");
private static ulong _lastUpdate = Util.GetTickCount64();
public static ulong Pressed { get; set; }

View File

@ -15,8 +15,8 @@ using System.Resources;
[assembly: AssemblyCulture("")]
// Version informationr(
[assembly: AssemblyVersion("1.5.4.4")]
[assembly: AssemblyFileVersion("1.5.4.4")]
// Version information
[assembly: AssemblyVersion("1.5.4.7")]
[assembly: AssemblyFileVersion("1.5.4.7")]
[assembly: NeutralResourcesLanguageAttribute( "en-US" )]

View File

@ -90,7 +90,7 @@
<Reference Include="ICSharpCode.SharpZipLib, Version=1.3.3.11, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
<HintPath>..\packages\SharpZipLib.1.3.3\lib\net45\ICSharpCode.SharpZipLib.dll</HintPath>
</Reference>
<Reference Include="LemonUI.SHVDN3, Version=1.7.0.0, Culture=neutral, processorArchitecture=AMD64">
<Reference Include="LemonUI.SHVDN3, Version=1.10.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\libs\LemonUI.SHVDN3.dll</HintPath>
</Reference>

View File

@ -91,7 +91,7 @@ namespace RageCoop.Client.Scripting
/// <summary>
/// The local player is dead
/// </summary>
public static event EmptyEvent OnPlayerDied;
public static event EventHandler<string> OnPlayerDied;
/// <summary>
/// A local vehicle is spawned
@ -133,7 +133,7 @@ namespace RageCoop.Client.Scripting
internal static void InvokeVehicleDeleted(SyncedVehicle v) { OnVehicleDeleted?.Invoke(null, v); }
internal static void InvokePedSpawned(SyncedPed p) { OnPedSpawned?.Invoke(null, p); }
internal static void InvokePedDeleted(SyncedPed p) { OnPedDeleted?.Invoke(null, p); }
internal static void InvokePlayerDied() { OnPlayerDied?.Invoke(); }
internal static void InvokePlayerDied(string m) { OnPlayerDied?.Invoke(null, m); }
internal static void InvokeTick() { OnTick?.Invoke(); }
internal static void InvokeKeyDown(object s, KeyEventArgs e) { OnKeyDown?.Invoke(s, e); }

View File

@ -16,7 +16,7 @@ namespace RageCoop.Client.Scripting
{
API.Events.OnPedDeleted += (s, p) => { API.SendCustomEvent(CustomEvents.OnPedDeleted, p.ID); };
API.Events.OnVehicleDeleted += (s, p) => { API.SendCustomEvent(CustomEvents.OnVehicleDeleted, p.ID); };
API.Events.OnPlayerDied += () => { API.SendCustomEvent(CustomEvents.OnPlayerDied); };
API.Events.OnPlayerDied += (s, m) => { API.SendCustomEvent(CustomEvents.OnPlayerDied, m); };
API.RegisterCustomEventHandler(CustomEvents.SetAutoRespawn, SetAutoRespawn);
API.RegisterCustomEventHandler(CustomEvents.SetDisplayNameTag, SetDisplayNameTag);
@ -31,7 +31,7 @@ namespace RageCoop.Client.Scripting
API.RegisterCustomEventHandler(CustomEvents.UpdatePedBlip, UpdatePedBlip);
API.RegisterCustomEventHandler(CustomEvents.IsHost, (e) => { _isHost = (bool)e.Args[0]; });
API.RegisterCustomEventHandler(CustomEvents.WeatherTimeSync, WeatherTimeSync);
API.RegisterCustomEventHandler(CustomEvents.OnPlayerDied, (e) => { GTA.UI.Notification.Show($"~h~{e.Args[0]}~h~ died."); });
API.RegisterCustomEventHandler(CustomEvents.OnPlayerDied, (e) => { GTA.UI.Notification.PostTicker((string)e.Args[0], false); });
Task.Run(() =>
{
while (true)
@ -42,12 +42,11 @@ namespace RageCoop.Client.Scripting
{
unsafe
{
var time = World.CurrentTimeOfDay;
int weather1 = default(int);
int weather2 = default(int);
float percent2 = default(float);
Function.Call(Hash.GET_CURR_WEATHER_STATE, &weather1, &weather2, &percent2);
API.SendCustomEvent(CustomEvents.WeatherTimeSync, time.Hours, time.Minutes, time.Seconds, weather1, weather2, percent2);
API.SendCustomEvent(CustomEvents.WeatherTimeSync, GTA.Chrono.GameClock.Hour, GTA.Chrono.GameClock.Minute, GTA.Chrono.GameClock.Second, weather1, weather2, percent2);
}
});
}
@ -59,7 +58,9 @@ namespace RageCoop.Client.Scripting
private void WeatherTimeSync(CustomEventReceivedArgs e)
{
World.CurrentTimeOfDay = new TimeSpan((int)e.Args[0], (int)e.Args[1], (int)e.Args[2]);
GTA.Chrono.GameClock.Hour = (int)e.Args[0];
GTA.Chrono.GameClock.Minute = (int)e.Args[1];
GTA.Chrono.GameClock.Second = (int)e.Args[2];
Function.Call(Hash.SET_CURR_WEATHER_STATE, (int)e.Args[3], (int)e.Args[4], (float)e.Args[5]);
}

View File

@ -67,6 +67,7 @@ namespace RageCoop.Client
/// The game won't spawn more NPC traffic if the limit is exceeded. -1 for unlimited (not recommended).
/// </summary>
public int WorldPedSoftLimit { get; set; } = 30;
/// <summary>
/// The directory where log and resources downloaded from server will be placed.
/// </summary>
@ -76,5 +77,15 @@ namespace RageCoop.Client
/// Show the owner name of the entity you're aiming at
/// </summary>
public bool ShowEntityOwnerName { get; set; } = false;
/// <summary>
/// Show other player's nametag on your screen
/// </summary>
public bool ShowPlayerNameTag { get; set; } = true;
/// <summary>
/// Show other player's blip on map
/// </summary>
public bool ShowPlayerBlip { get; set; } = true;
}
}

View File

@ -28,8 +28,8 @@ namespace RageCoop.Client
MainPed = p;
OwnerID = Main.LocalPlayerID;
Function.Call(Hash.SET_PED_IS_IGNORED_BY_AUTO_OPEN_DOORS, false);
MainPed.SetConfigFlag((int)PedConfigFlags.CPED_CONFIG_FLAG_DisableHurt, true);
//Function.Call(Hash.SET_PED_IS_IGNORED_BY_AUTO_OPEN_DOORS, false);
MainPed.SetConfigFlag(PedConfigFlagToggles.DisableHurt, true);
// MainPed.SetConfigFlag((int)PedConfigFlags.CPED_CONFIG_FLAG_DisableMelee, true);
}
@ -76,12 +76,13 @@ namespace RageCoop.Client
}
}
if (((byte)BlipColor == 255) && (PedBlip != null))
if (!Main.Settings.ShowPlayerBlip && (byte)BlipColor != 255) BlipColor = (BlipColor)255;
if ((byte)BlipColor == 255 && PedBlip != null)
{
PedBlip.Delete();
PedBlip = null;
}
else if (((byte)BlipColor != 255) && PedBlip == null)
else if ((byte)BlipColor != 255 && PedBlip == null)
{
PedBlip = MainPed.AddBlip();
@ -140,6 +141,12 @@ namespace RageCoop.Client
}
}
if (!IsPlayer && Health <= 0 && !MainPed.IsDead)
{
MainPed.Kill();
return;
}
if (Speed >= 4)
{
DisplayInVehicle();
@ -170,7 +177,7 @@ namespace RageCoop.Client
private void RenderNameTag()
{
if (!Owner.DisplayNameTag || (MainPed == null) || !MainPed.IsVisible || !MainPed.IsInRange(Main.PlayerPosition, 40f))
if (!Owner.DisplayNameTag || !Main.Settings.ShowPlayerNameTag || MainPed == null || !MainPed.IsVisible || !MainPed.IsInRange(Main.PlayerPosition, 40f))
{
return;
}
@ -204,7 +211,7 @@ namespace RageCoop.Client
MainPed = null;
}
if (PedBlip != null && PedBlip.Exists())
if (PedBlip != null)
{
PedBlip.Delete();
PedBlip = null;
@ -238,16 +245,15 @@ namespace RageCoop.Client
Function.Call(Hash.SET_PED_IS_IGNORED_BY_AUTO_OPEN_DOORS, false);
Function.Call(Hash.SET_PED_CAN_EVASIVE_DIVE, MainPed.Handle, false);
MainPed.SetConfigFlag((int)PedConfigFlags.CPED_CONFIG_FLAG_DrownsInWater, false);
MainPed.SetConfigFlag((int)PedConfigFlags.CPED_CONFIG_FLAG_DisableHurt, true);
MainPed.SetConfigFlag((int)PedConfigFlags.CPED_CONFIG_FLAG_DisableExplosionReactions, true);
MainPed.SetConfigFlag((int)PedConfigFlags.CPED_CONFIG_FLAG_AvoidTearGas, false);
MainPed.SetConfigFlag((int)PedConfigFlags.CPED_CONFIG_FLAG_IgnoreBeingOnFire, true);
MainPed.SetConfigFlag((int)PedConfigFlags.CPED_CONFIG_FLAG_DisableEvasiveDives, true);
MainPed.SetConfigFlag((int)PedConfigFlags.CPED_CONFIG_FLAG_DisablePanicInVehicle, true);
MainPed.SetConfigFlag((int)PedConfigFlags.CPED_CONFIG_FLAG_BlockNonTemporaryEvents, true);
MainPed.SetConfigFlag((int)PedConfigFlags.CPED_CONFIG_FLAG_DisableShockingEvents, true);
MainPed.SetConfigFlag((int)PedConfigFlags.CPED_CONFIG_FLAG_DisableHurt, true);
MainPed.SetConfigFlag(PedConfigFlagToggles.DrownsInWater, false);
MainPed.SetConfigFlag(PedConfigFlagToggles.DisableHurt, true);
MainPed.SetConfigFlag(PedConfigFlagToggles.DisableExplosionReactions, true);
MainPed.SetConfigFlag(PedConfigFlagToggles.AvoidTearGas, false);
MainPed.SetConfigFlag(PedConfigFlagToggles.IgnoreBeingOnFire, true);
MainPed.SetConfigFlag(PedConfigFlagToggles.DisableEvasiveDives, true);
MainPed.SetConfigFlag(PedConfigFlagToggles.DisablePanicInVehicle, true);
MainPed.SetConfigFlag(PedConfigFlagToggles.BlockNonTemporaryEvents, true);
MainPed.SetConfigFlag(PedConfigFlagToggles.DisableShockingEvents, true);
SetClothes();
@ -419,7 +425,7 @@ namespace RageCoop.Client
}
_lastIsJumping = false;
if (IsRagdoll || Health == 0)
if (IsRagdoll || (IsPlayer && Health == 0))
{
if (!MainPed.IsRagdoll)
{
@ -539,7 +545,7 @@ namespace RageCoop.Client
{
if (Velocity == default)
{
MainPed.Task.AimAt(AimCoords, 1000);
MainPed.Task.AimGunAtPosition(AimCoords, 1000);
}
else
{
@ -597,6 +603,8 @@ namespace RageCoop.Client
MainPed.Task.StandStill(2000);
LastMoving = false;
}
if (MainPed.IsTaskActive(TaskType.CTaskDiveToGround)) MainPed.Task.ClearAll();
break;
}
SmoothTransition();

View File

@ -4,6 +4,7 @@ using GTA.Native;
using RageCoop.Core;
using System;
using System.Collections.Generic;
using System.Linq;
namespace RageCoop.Client
{
@ -141,7 +142,7 @@ namespace RageCoop.Client
if (LightsOn != MainVehicle.AreLightsOn)
{
MainVehicle.AreLightsOn = LightsOn;
MainVehicle.SetScriptedLightSetting(LightsOn ? ScriptedVehicleLightSetting.SetVehicleLightsOn : ScriptedVehicleLightSetting.SetVehicleLightsOff);
}
if (HighBeamsOn != MainVehicle.AreHighBeamsOn)
@ -284,10 +285,10 @@ namespace RageCoop.Client
if (IsFlipped || (calirot = GetCalibrationRotation()).Length() > 50)
{
MainVehicle.Quaternion = Quaternion.Slerp(MainVehicle.ReadQuaternion(), Quaternion, 0.5f);
MainVehicle.RotationVelocity = RotationVelocity;
MainVehicle.LocalRotationVelocity = RotationVelocity;
return;
}
MainVehicle.RotationVelocity = RotationVelocity + calirot * 0.2f;
MainVehicle.LocalRotationVelocity = RotationVelocity + calirot * 0.2f;
}
private Vector3 GetCalibrationRotation()
{
@ -307,6 +308,16 @@ namespace RageCoop.Client
}
private bool CreateVehicle()
{
var existing = World.GetNearbyVehicles(Position, 2).ToList().FirstOrDefault();
if (existing != null && existing != MainVehicle)
{
if (EntityPool.VehiclesByHandle.ContainsKey(existing.Handle))
{
EntityPool.RemoveVehicle(ID);
return false;
}
existing.Delete();
}
MainVehicle?.Delete();
MainVehicle = Util.CreateVehicle(Model, Position);
if (!Model.IsInCdImage)
@ -337,41 +348,5 @@ namespace RageCoop.Client
Model.MarkAsNoLongerNeeded();
return true;
}
#region -- PEDALING --
/*
* Thanks to @oldnapalm.
*/
private string PedalingAnimDict()
{
switch ((VehicleHash)Model)
{
case VehicleHash.Bmx:
return "veh@bicycle@bmx@front@base";
case VehicleHash.Cruiser:
return "veh@bicycle@cruiserfront@base";
case VehicleHash.Scorcher:
return "veh@bicycle@mountainfront@base";
default:
return "veh@bicycle@roadfront@base";
}
}
private string PedalingAnimName(bool fast)
{
return fast ? "fast_pedal_char" : "cruise_pedal_char";
}
private void StartPedalingAnim(bool fast)
{
MainVehicle.Driver?.Task.PlayAnimation(PedalingAnimDict(), PedalingAnimName(fast), 8.0f, -8.0f, -1, AnimationFlags.Loop | AnimationFlags.Secondary, 1.0f);
}
private void StopPedalingAnim(bool fast)
{
MainVehicle.Driver.Task.ClearAnimation(PedalingAnimDict(), PedalingAnimName(fast));
}
#endregion
}
}

View File

@ -43,7 +43,7 @@ namespace RageCoop.Client
#endregion
public static void Cleanup(bool keepPlayer = true, bool keepMine = true)
{
foreach (var ped in PedsByID.Values)
foreach (var ped in PedsByID.Values.ToArray())
{
if ((keepPlayer && (ped.ID == Main.LocalPlayerID)) || (keepMine && (ped.OwnerID == Main.LocalPlayerID))) { continue; }
RemovePed(ped.ID);
@ -51,7 +51,7 @@ namespace RageCoop.Client
PedsByID.Clear();
PedsByHandle.Clear();
foreach (int id in new List<int>(VehiclesByID.Keys))
foreach (int id in VehiclesByID.Keys.ToArray())
{
if (keepMine && (VehiclesByID[id].OwnerID == Main.LocalPlayerID)) { continue; }
RemoveVehicle(id);
@ -277,8 +277,8 @@ namespace RageCoop.Client
{
ProjectilesByHandle.Remove(p.Handle);
}
Main.Logger.Debug($"Removing projectile {sp.ID}. Reason:{reason}");
p.Explode();
//Main.Logger.Debug($"Removing projectile {sp.ID}. Reason:{reason}");
if (sp.Exploded) p.Explode();
}
ProjectilesByID.Remove(id);
}
@ -359,21 +359,24 @@ namespace RageCoop.Client
lock (PedsLock)
{
AddPlayer();
var mainCharacters = new List<PedHash> { PedHash.Michael, PedHash.Franklin, PedHash.Franklin02, PedHash.Trevor };
foreach (Ped p in allPeds)
{
SyncedPed c = GetPedByHandle(p.Handle);
if (c == null && (p != Game.Player.Character))
if (!PedsByHandle.ContainsKey(p.Handle) && p != Game.Player.Character && !mainCharacters.Contains((PedHash)p.Model.Hash))
{
if (allPeds.Length > Main.Settings.WorldPedSoftLimit && p.PopulationType == EntityPopulationType.RandomAmbient && !p.IsInVehicle())
if (PedsByID.Count(x => x.Value.IsLocal) > Main.Settings.WorldPedSoftLimit)
{
p.Delete();
continue;
if (p.PopulationType == EntityPopulationType.RandomAmbient && !p.IsInVehicle())
{
p.Delete();
continue;
}
if (p.PopulationType == EntityPopulationType.RandomScenario) continue;
}
// Main.Logger.Trace($"Creating SyncEntity for ped, handle:{p.Handle}");
c = new SyncedPed(p);
Add(c);
Add(new SyncedPed(p));
}
}
#if BENCHMARK
@ -437,10 +440,9 @@ namespace RageCoop.Client
{
if (!VehiclesByHandle.ContainsKey(veh.Handle))
{
if (allVehicles.Length > Main.Settings.WorldVehicleSoftLimit)
if (VehiclesByID.Count(x => x.Value.IsLocal) > Main.Settings.WorldVehicleSoftLimit)
{
var type = veh.PopulationType;
if (type == EntityPopulationType.RandomAmbient || type == EntityPopulationType.RandomParked)
if (veh.PopulationType == EntityPopulationType.RandomAmbient || veh.PopulationType == EntityPopulationType.RandomParked)
{
foreach (var p in veh.Occupants)
{

View File

@ -126,7 +126,7 @@ namespace RageCoop.Client
}
var p = EntityPool.GetPedByID(ownerID)?.MainPed;
if (p == null) { p = Game.Player.Character; Main.Logger.Warning("Failed to find owner for bullet"); }
if (p == null) { return; /* p = Game.Player.Character; Main.Logger.Warning("Failed to find owner for bullet"); */ }
if (!CorePFXAsset.IsLoaded) { CorePFXAsset.Request(); }
if (_lastWeaponHash != weaponHash)
{
@ -135,7 +135,7 @@ namespace RageCoop.Client
_lastWeaponHash = weaponHash;
}
if (!_weaponAsset.IsLoaded) { _weaponAsset.Request(); }
World.ShootBullet(start, end, p, _weaponAsset, (int)p.GetWeaponDamage(weaponHash));
World.ShootSingleBullet(start, end, (int)p.GetWeaponDamage(weaponHash), _weaponAsset, p);
Prop w;
if (((w = p.Weapons.CurrentWeaponObject) != null) && (p.VehicleWeapon == VehicleWeaponHash.Invalid))
{

View File

@ -40,7 +40,7 @@ namespace RageCoop.Client
{
// Weapon/radio wheel slow-mo patch
// Thanks @CamxxCore, https://github.com/CamxxCore/GTAVWeaponWheelMod
var result = NativeMemory.FindPattern("\x38\x51\x64\x74\x19", "xxxxx");
var result = MemScanner.FindPatternBmh("\x38\x51\x64\x74\x19", "xxxxx");
if (result == null) { throw new NotSupportedException("Can't find memory pattern to patch weapon/radio slow-mo"); }
var address = result + 26;
address = address + *(int*)address + 4u;
@ -91,7 +91,7 @@ namespace RageCoop.Client
var foundOffsets = new List<int>(100);
for (int i = 0; i <= range; i++)
{
var val = NativeMemory.ReadFloat(start + i);
var val = MemDataMarshal.ReadFloat(start + i);
if (Math.Abs(val - toSearch) < tolerance)
{
foundOffsets.Add(i);

View File

@ -201,7 +201,7 @@ namespace RageCoop.Client
return v;
}
public static void ApplyForce(this Entity e, int boneIndex, Vector3 direction, Vector3 rotation = default(Vector3), ForceType forceType = ForceType.MaxForceRot2)
public static void ApplyForce(this Entity e, int boneIndex, Vector3 direction, Vector3 rotation = default(Vector3), ForceType forceType = ForceType.ExternalImpulse)
{
Function.Call(Hash.APPLY_FORCE_TO_ENTITY, e.Handle, forceType, direction.X, direction.Y, direction.Z, rotation.X, rotation.Y, rotation.Z, boneIndex, false, true, true, false, true);
}
@ -244,7 +244,7 @@ namespace RageCoop.Client
}
lineList.Add("ReloadKey=Insert");
File.WriteAllLines("ScriptHookVDotNet.ini", lineList.ToArray());
GTA.UI.Notification.Show("Reload cannot be performed automatically, please type \"Reload()\" manually in the SHVDN console.");
GTA.UI.Notification.PostTicker("Reload cannot be performed automatically, please type \"Reload()\" manually in the SHVDN console.", false);
}
Keys key = (Keys)Enum.Parse(typeof(Keys), reloadKey, true);
@ -259,7 +259,7 @@ namespace RageCoop.Client
}
catch (Exception ex)
{
GTA.UI.Notification.Show(ex.Message);
GTA.UI.Notification.PostTicker(ex.Message, false);
}
PostMessage(System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle, WM_KEYDOWN, (int)key, 0);

View File

@ -174,12 +174,12 @@ namespace RageCoop.Client
}
continue;
}
else if (door.IsBroken)
/*else if (door.IsBroken) // causes break/repair loop in some situations
{
// The vehicle can only fix a door if the vehicle was completely fixed
veh.Repair();
return;
}
}*/
if ((model.OpenedDoors & (byte)(1 << i)) != 0)
{
if ((!door.IsOpen) && (!door.IsBroken))
@ -196,10 +196,10 @@ namespace RageCoop.Client
{
veh.Windows[(VehicleWindowIndex)i].Smash();
}
else if (!veh.Windows[(VehicleWindowIndex)i].IsIntact)
/*else if (!veh.Windows[(VehicleWindowIndex)i].IsIntact) // causes smash/repair loop in some situations
{
veh.Windows[(VehicleWindowIndex)i].Repair();
}
}*/
}
foreach (VehicleWheel wheel in veh.Wheels)

View File

@ -120,7 +120,7 @@ namespace RageCoop.Client
if ((c == null) || (c.IsLocal && (ped.Handle != Game.Player.Character.Handle) && ped.PopulationType != EntityPopulationType.Mission))
{
Main.Logger.Trace($"Removing ped {ped.Handle}. Reason:RemoveTraffic");
// Main.Logger.Trace($"Removing ped {ped.Handle}. Reason:RemoveTraffic");
ped.CurrentVehicle?.Delete();
ped.Kill();
ped.Delete();

View File

@ -15,7 +15,7 @@ using System.Resources;
[assembly: AssemblyCulture("")]
// Version information
[assembly: AssemblyVersion("1.5.4.3")]
[assembly: AssemblyFileVersion("1.5.4.3")]
[assembly: AssemblyVersion("1.5.4.5")]
[assembly: AssemblyFileVersion("1.5.4.5")]
[assembly: NeutralResourcesLanguageAttribute( "en-US" )]

View File

@ -38,7 +38,7 @@ namespace RageCoop.Server.Scripting
});
API.RegisterCustomEventHandler(CustomEvents.OnPlayerDied, (e) =>
{
API.SendCustomEventQueued(API.GetAllClients().Values.Where(x => x != e.Client).ToList(), CustomEvents.OnPlayerDied, e.Client.Username);
API.SendCustomEventQueued(API.GetAllClients().Values.Where(x => x != e.Client).ToList(), CustomEvents.OnPlayerDied, e.Args);
});
API.Events.OnChatMessage += (s, e) =>
Server.Logger?.Info((e.Client?.Username ?? e.ClaimedSender ?? "Unknown") + ": " + e.Message);

Binary file not shown.

Binary file not shown.

Binary file not shown.