From 60f55e0eeb0105c048a556b32953b4ab014f80ab Mon Sep 17 00:00:00 2001 From: hydrant Date: Thu, 27 May 2021 21:06:20 +0200 Subject: [PATCH] hanf vielleicht fertig --- .../Interaction/factioninteraction.ts | 31 +- ReallifeGamemode.Client/drugs/hanf.ts | 133 +- ReallifeGamemode.Client/util/animationSync.ts | 14 +- .../util/attachmentMngr.ts | 7 +- ReallifeGamemode.Database/Entities/User.cs | 4 + ...901_AddUserCannabisSeedBuyData.Designer.cs | 2229 +++++++++++++++++ ...210527144901_AddUserCannabisSeedBuyData.cs | 33 + .../DatabaseContextModelSnapshot.cs | 6 + ReallifeGamemode.Server/BaseScript.cs | 2 +- ReallifeGamemode.Server/Events/Death.cs | 8 + ReallifeGamemode.Server/Events/Disconnect.cs | 8 + ReallifeGamemode.Server/Events/Key.cs | 92 +- ReallifeGamemode.Server/Events/Vehicle.cs | 6 + .../Inventory/Interfaces/IIllegalItem.cs | 11 + .../Inventory/Items/Cannabis.cs | 6 +- .../Inventory/Items/CannabisSeeds.cs | 8 +- .../Inventory/Items/Joint.cs | 29 +- .../Managers/HanfManager.cs | 253 +- .../Managers/InteractionManager.cs | 145 ++ .../Managers/InventoryManager.cs | 27 +- 20 files changed, 2996 insertions(+), 56 deletions(-) create mode 100644 ReallifeGamemode.Database/Migrations/20210527144901_AddUserCannabisSeedBuyData.Designer.cs create mode 100644 ReallifeGamemode.Database/Migrations/20210527144901_AddUserCannabisSeedBuyData.cs create mode 100644 ReallifeGamemode.Server/Inventory/Interfaces/IIllegalItem.cs diff --git a/ReallifeGamemode.Client/Interaction/factioninteraction.ts b/ReallifeGamemode.Client/Interaction/factioninteraction.ts index 1b75b5ed..506e47a1 100644 --- a/ReallifeGamemode.Client/Interaction/factioninteraction.ts +++ b/ReallifeGamemode.Client/Interaction/factioninteraction.ts @@ -31,7 +31,7 @@ export default function factionInteraction(globalData: IGlobalData) { var ticketName: string; var pointsName: string; - var factionInteractionMenu; + var factionInteractionMenu: NativeUI.Menu; var healTaskMenuMedic; var reviveTaskMenuMedic; var insDate; @@ -42,7 +42,10 @@ export default function factionInteraction(globalData: IGlobalData) { //LSPD let ticketTaskMenuLSPD; let pointsTaskMenuLSPD; - let wantedsMenuLSPD + let wantedsMenuLSPD; + + let friskUserMenuItem: NativeUI.UIMenuItem; + let friskVehicleMenuItem: NativeUI.UIMenuItem; if (userFactionId == 1 || userFactionId == 3) { if (isDuty) { mp.gui.chat.activate(false); @@ -59,6 +62,12 @@ export default function factionInteraction(globalData: IGlobalData) { wantedsMenuLSPD = new UIMenuItem("Verbrecher Liste"); factionInteractionMenu.AddItem(wantedsMenuLSPD); + friskUserMenuItem = new UIMenuItem("Spieler durchsuchen", "Einen Spieler auf illegale Gegenstände durchsuchen."); + factionInteractionMenu.AddItem(friskUserMenuItem); + + friskVehicleMenuItem = new UIMenuItem("Fahrzeug durchsuchen", "Das nächste Fahrzeug auf illegale Gegenstände durchsuchen.") + factionInteractionMenu.AddItem(friskVehicleMenuItem); + /*TaskMenuLSPD = new UIMenuItem(""); TaskMenuLSPD.SetRightLabel(""); factionInteractionMenu.AddItem(TaskMenuLSPD);*/ //weiteres @@ -107,6 +116,20 @@ export default function factionInteraction(globalData: IGlobalData) { globalData.InMenu = false; mp.events.callRemote("CLIENT:wantedlist"); break; + + case friskUserMenuItem: + factionInteractionMenu.Visible = false; + var input = new InputHelper("Welchem Spieler möchtest du Strafpunkte geben (Name / ID)?", globalData); + input.show(); + input.getValue(name => { + mp.events.callRemote("CLIENT:InteractionMenu_LSPD_FriskUser", name); + globalData.InMenu = false; + }); + break; + + case friskVehicleMenuItem: + factionInteractionMenu.Close(); + mp.events.callRemote("CLIENT:InteractionMenu_LSPD_FriskVehicle"); } }); @@ -273,7 +296,7 @@ export default function factionInteraction(globalData: IGlobalData) { mp.gui.chat.activate(true); globalData.InMenu = false; mp.events.callRemote("updateMedicTask", 1, activeTask.Victim, true); - mp.events.call("destroyMedicTaskCheckpoint"); + mp.events.call("destroyMedicTaskCheckpoint"); break; } @@ -357,7 +380,7 @@ export default function factionInteraction(globalData: IGlobalData) { } aTask1.SetRightLabel(mp.game.gameplay.getDistanceBetweenCoords(player.position.x, player.position.y, player.position.z, tasks[i].Position.x, tasks[i].Position.y, tasks[i].Position.z, true).toFixed(2).toString() + " ~g~m"); - healTaskMenuMedic.AddItem(aTask1); + healTaskMenuMedic.AddItem(aTask1); } let backItem1 = new UIMenuItem("Zur\u00fcck", "Zur\u00fcck zur Fraktionsinteraktion."); diff --git a/ReallifeGamemode.Client/drugs/hanf.ts b/ReallifeGamemode.Client/drugs/hanf.ts index 3dd44235..4c5339c1 100644 --- a/ReallifeGamemode.Client/drugs/hanf.ts +++ b/ReallifeGamemode.Client/drugs/hanf.ts @@ -5,7 +5,7 @@ import { getAnimFromId } from "../util/animationSync"; import { getCreatedPedByName } from "../Ped/PedCreator"; import KeyBinder from 'ragemp-better-bindings'; -const hanfPlantObjects = { +export const hanfPlantObjects = { stage1: mp.game.joaat('bkr_prop_weed_bud_pruned_01a'), stage2: mp.game.joaat('bkr_prop_weed_bud_01b'), stage3: mp.game.joaat('prop_weed_02'), @@ -43,7 +43,7 @@ export default function hanfSystem(globalData: IGlobalData) { let currentlyPlanting: boolean = false; let lastPlantingState = true; - mp.events.add("SERVER:Hanf_BuySeed", price => { + mp.events.add("SERVER:Hanf_BuySeed", (maxSeedsToBuy, price) => { if (globalData.InMenu || globalData.InChat) { return; } @@ -54,7 +54,7 @@ export default function hanfSystem(globalData: IGlobalData) { var seedsToBuy = 0; - var countItems = [...Array(50).keys()].map(x => x + 1); + var countItems = [...Array(maxSeedsToBuy).keys()].map(x => x + 1); var soloPriceItem = createMenuItem("Einzelpreis", "Preis pro Samen", item => { item.SetRightLabel("$" + moneyformat(price)); @@ -93,6 +93,56 @@ export default function hanfSystem(globalData: IGlobalData) { menu.Open(); }); + mp.events.add("SERVER:Hanf_SellCannabisMenu", (maxCannabisToSell, price) => { + if (globalData.InMenu || globalData.InChat) { + return; + } + + globalData.InMenu = true; + + var menu = new Menu("Cannabis verkaufen", "Verkaufe dein Cannabis", new Point(50, 50)); + + var cannabisToSell = 0; + + var countItems = [...Array(maxCannabisToSell).keys()].map(x => x + 1); + + var soloPriceItem = createMenuItem("Einzelpreis", "Preis pro Hanfblüte", item => { + item.SetRightLabel("$" + moneyformat(price)); + }); + menu.AddItem(soloPriceItem); + + var countItem = new UIMenuListItem("Anzahl", "Wähle die Anzahl der Blüten aus", new ItemsCollection(countItems), 0); + menu.AddItem(countItem); + + var buyItem = new UIMenuItem("Verkaufen", "Verkaufe dein Cannabis"); + buyItem.BackColor = new Color(0, 100, 0); + buyItem.HighlightedBackColor = new Color(0, 150, 0); + menu.AddItem(buyItem); + + var completePriceItem = new UIMenuItem("Gesamtpreis", "Preis für alle Blüten"); + menu.AddItem(completePriceItem); + + menu.ListChange.on((item, index) => { + if (item === countItem) { + cannabisToSell = Number(countItem.SelectedValue); + completePriceItem.SetRightLabel("$" + moneyformat(cannabisToSell * price)); + } + }); + + menu.ItemSelect.on((item, index) => { + if (item === buyItem) { + mp.events.callRemote("CLIENT:Hanf_SellCannabis", cannabisToSell); + menu.Close(); + } + }); + + menu.MenuClose.on(() => { + globalData.InMenu = false; + }); + + menu.Open(); + }); + mp.events.add("SERVER:Hanf_PlayManufacturerAnim", animId => { var anim = getAnimFromId(animId); var npc = getCreatedPedByName("hanf_verarbeiter_typ"); @@ -154,9 +204,9 @@ export default function hanfSystem(globalData: IGlobalData) { return false; } - //if (!isSurfaceAllowed()) { - // return false; - //} + if (!isSurfaceAllowed()) { + return false; + } if (currentPlantingPreviewObject) { var objectPos = getPlantPreviewPosition(); @@ -177,14 +227,29 @@ export default function hanfSystem(globalData: IGlobalData) { const GET_RAYCAST_RESULT_NATIVE = "0x65287525D951F6BE"; function isSurfaceAllowed() { + return true; const player = mp.players.local; - var position = player.position; - var raycast = mp.game.invoke(RAYCAST_POINT_TO_POINT_NATIVE, position.x, position.y, position.z + 5, position.x, position.y, position.z - 5, -1, undefined, 0); + var position = getPlantPreviewPosition(); + var raycast = mp.game.invoke(RAYCAST_POINT_TO_POINT_NATIVE, position.x, position.y, position.z + 5, position.x, position.y, position.z - 5, 1, 0, 7); mp.gui.chat.push("raycast = " + raycast); - var hit: boolean, coord: Vector3Mp, surfaceNormal: Vector3Mp, materialHash: number, entityHit: EntityMp; - var raycastResult = mp.game.invoke(GET_RAYCAST_RESULT_NATIVE, raycast, hit, coord, surfaceNormal, materialHash, entityHit); + var resultObj = { + hit: [false], + coord: [new mp.Vector3()], + surface: [new mp.Vector3()], + material: [0], + entityHit: [null] + }; - mp.gui.chat.push("result: " + raycastResult + ", hit = " + hit + ", test = " + materialHash); + var raycastResult = -1; + var retries = 10; + + do { + raycastResult = mp.game.invoke(GET_RAYCAST_RESULT_NATIVE, raycast, resultObj.hit, resultObj.coord, resultObj.surface, resultObj.material, resultObj.entityHit); + retries--; + } while (raycastResult != 0 && raycastResult != 2 && retries > 0); + + + mp.gui.chat.push("result: " + raycastResult + ", result = " + JSON.stringify(resultObj)); return true; } @@ -270,17 +335,15 @@ export default function hanfSystem(globalData: IGlobalData) { mp.events.add("SERVER:Hanf_UpdateHanfData", dataJson => { mp.console.logInfo(dataJson); + var data: Array = >JSON.parse(dataJson) var newPlants = data.filter(d => currentHanfData.filter(x => x.Id === d.Id).length == 0); var removedPlants = currentHanfData.filter(d => data.filter(x => x.Id === d.Id).length == 0); var existingPlants = data.filter(d => currentHanfData.filter(x => x.Id === d.Id).length == 1); - mp.gui.chat.push(`new: ${newPlants.length}, removed: ${removedPlants.length}, existing: ${existingPlants.length}`); - newPlants.forEach(plant => { var model = getPlantModel(plant); - mp.gui.chat.push("new id: " + plant.Id + ", model = " + model); var object = mp.objects.new(getPlantModel(plant), new mp.Vector3(plant.X, plant.Y, plant.Z)); hanfDataIdToObjectMap.set(plant.Id, object); @@ -292,7 +355,6 @@ export default function hanfSystem(globalData: IGlobalData) { }); removedPlants.forEach(plant => { - //mp.gui.chat.push("removed id: " + plant.Id); var object = hanfDataIdToObjectMap.get(plant.Id); hanfDataIdToObjectMap.delete(plant.Id); object.destroy(); @@ -302,11 +364,9 @@ export default function hanfSystem(globalData: IGlobalData) { }); existingPlants.forEach(plant => { - //mp.gui.chat.push("existing plant: " + plant.Id + ", plant time = " + new Date(plant.Time).toLocaleTimeString() + ", current time = " + new Date().toLocaleTimeString()); var object = hanfDataIdToObjectMap.get(plant.Id); var model = getPlantModel(plant); if (model != object.model) { - //mp.gui.chat.push("existing plant: " + plant.Id + ", changing model to = " + model); object.destroy(); var object = mp.objects.new(model, new mp.Vector3(plant.X, plant.Y, plant.Z)); hanfDataIdToObjectMap.delete(plant.Id); @@ -341,4 +401,43 @@ export default function hanfSystem(globalData: IGlobalData) { return model; } + + mp.events.addProc("SERVER:Hanf_GetModelToGivePlayer", id => { + var plant = currentHanfData.filter(x => x.Id == id)[0]; + var model = getPlantModel(plant); + if (model == hanfPlantObjects.stage1) { + return 1; + } else if (model == hanfPlantObjects.stage3) { + return 2; + } else if (model == hanfPlantObjects.stage4) { + return 3; + } + }); + + //var rotationTestObject: ObjectMp = null; + //var a1: number, a2: number, a3: number, a4: number, a5: number, a6: number; + //mp.events.add(RageEnums.EventKey.PLAYER_COMMAND, (f) => { + // var args = f.split(' '); + // if (args[0] != "a") { + // return; + // } + + // a1 = parseFloat(args[1] || "0"); + // a2 = parseFloat(args[2] || "0"); + // a3 = parseFloat(args[3] || "0"); + // a4 = parseFloat(args[4] || "0"); + // a5 = parseFloat(args[5] || "0"); + // a6 = parseFloat(args[6] || "0"); + + // mp.gui.chat.push(`a1: ${a1.toFixed(2)}, a2: ${a2.toFixed(2)}, a3: ${a3.toFixed(2)}, a4: ${a4.toFixed(2)}, a5: ${a5.toFixed(2)}, a6: ${a6.toFixed(2)},`) + + // if (rotationTestObject != null) { + // rotationTestObject.attachTo(Number(mp.players.local.handle), mp.players.local.getBoneIndex(57005), a1, a2, a3, a4, a5, a6, true, false, false, false, 0, true); + // return; + // } + + // rotationTestObject = mp.objects.new(mp.game.joaat("prop_cs_trowel"), mp.players.local.position, { + // alpha: 255 + // }); + //}); } \ No newline at end of file diff --git a/ReallifeGamemode.Client/util/animationSync.ts b/ReallifeGamemode.Client/util/animationSync.ts index e0842af2..02f51191 100644 --- a/ReallifeGamemode.Client/util/animationSync.ts +++ b/ReallifeGamemode.Client/util/animationSync.ts @@ -4,7 +4,7 @@ const animationSyncData = { animations: [], - register: function (name, animDict, animName, duration, loop, flag, endless) { + register: function (name, animDict, animName, duration, loop, flag, endless, eventAfter: string = null) { let id = mp.game.joaat(name); if (!this.animations.hasOwnProperty(id)) { @@ -17,7 +17,8 @@ const animationSyncData = duration: duration, loop: loop, flag: flag, - endless: endless + endless: endless, + eventAfter: eventAfter }; } else { mp.game.graphics.notify("Animation Sync Error: ~r~Duplicate Entry"); @@ -50,6 +51,10 @@ export default function animationSync() { animationSyncData.register("hup", "mp_am_hold_up", "handsup_base", -1, true, 50, true); animationSyncData.register("carryBox", "anim@heists@box_carry@", "idle", -1, true, 50, true); animationSyncData.register("manufacturJoint", "anim@mp_snowball", "pickup_snowball", 1000 * 10, false, 1, false); + //animationSyncData.register("harvestPlantEnter", "amb@world_human_gardener_plant@female@enter", "enter_female", 1000 * 3.5, false, 1, false); + animationSyncData.register("harvestPlant", "amb@world_human_gardener_plant@male@base", "base", 1000 * 10, false, 1, false, "Hanf_FinishDiggingAnimation"); + //animationSyncData.register("harvestPlantExit", "amb@world_human_gardener_plant@female@exit", "exit_female", 1000 * 3.5, false, 1, false, "Hanf_FinishDiggingAnimation"); + animationSyncData.register("jointUse", "amb@world_human_smoking_pot@male@base", "base", 1000 * 10, false, 1, false); }); const animationBreakMessage = [ @@ -115,7 +120,7 @@ export default function animationSync() { let animData = animationSyncData.animations[index]; - let { id, name, animDict, animName, duration, loop, flag, endless } = animData; + let { id, name, animDict, animName, duration, loop, flag, endless, eventAfter } = animData; loadAnimDict(animDict, function () { mp.players.exists(entity) && 0 !== entity.handle && entity.taskPlayAnim(animDict, animName, 1, 0, duration, parseInt(flag), 0, !1, !1, !1) @@ -130,6 +135,9 @@ export default function animationSync() { let a = setTimeout(function () { clearTimeout(a); mp.events.callRemote("CLIENT:ClearAnimationData", true); + if (eventAfter) { + mp.events.callRemote("CLIENT:" + eventAfter); + } }, duration); } } diff --git a/ReallifeGamemode.Client/util/attachmentMngr.ts b/ReallifeGamemode.Client/util/attachmentMngr.ts index d46da114..82d32b94 100644 --- a/ReallifeGamemode.Client/util/attachmentMngr.ts +++ b/ReallifeGamemode.Client/util/attachmentMngr.ts @@ -1,4 +1,5 @@ import { IGame, IEntity } from "../game"; +import { hanfPlantObjects } from "../drugs/hanf"; export default function attachmentManager(game: IGame) { mp.events.add("SERVER:LoadAttachments", () => { @@ -9,6 +10,10 @@ export default function attachmentManager(game: IGame) { attachmentMngr.register("weapondeal1", "ex_office_swag_guns02", "chassis_dummy", new mp.Vector3(0, 0.8, 0), new mp.Vector3(0, 0, 0)); attachmentMngr.register("weapondeal2", "w_sg_pumpshotgun", "chassis_dummy", new mp.Vector3(0.4, 1.6, 0.62), new mp.Vector3(90, 0, 180)); attachmentMngr.register("handcuffs", "p_cs_cuffs_02_s", 28422, new mp.Vector3(-0.05, 0, 0), new mp.Vector3(90, 90, 0)); + attachmentMngr.register("shovel", "prop_cs_trowel", 28422, new mp.Vector3(0.1, 0.0, 0.0), new mp.Vector3(120, 70, 0)); + attachmentMngr.register("CannabisPlantInHand1", hanfPlantObjects.stage1, 28422, new mp.Vector3(), new mp.Vector3()); + attachmentMngr.register("CannabisPlantInHand2", hanfPlantObjects.stage3, 28422, new mp.Vector3(), new mp.Vector3()); + attachmentMngr.register("CannabisPlantInHand3", hanfPlantObjects.stage4, 28422, new mp.Vector3(), new mp.Vector3()); }); const attachmentMngr = @@ -140,7 +145,7 @@ export default function attachmentManager(game: IGame) { targetEntity, bone, offset.x, offset.y, offset.z, rotation.x, rotation.y, rotation.z, - false, false, false, false, 2, true + true, false, false, false, 0, true ); } diff --git a/ReallifeGamemode.Database/Entities/User.cs b/ReallifeGamemode.Database/Entities/User.cs index 197224eb..eec30f5b 100644 --- a/ReallifeGamemode.Database/Entities/User.cs +++ b/ReallifeGamemode.Database/Entities/User.cs @@ -129,6 +129,10 @@ namespace ReallifeGamemode.Database.Entities public bool FreeSurgery { get; set; } = true; + public DateTime? LastTimeBoughtCannabisSeeds { get; set; } + + public int CannabisSeedsBoughtToday { get; set; } + [NotMapped] public Player Player { diff --git a/ReallifeGamemode.Database/Migrations/20210527144901_AddUserCannabisSeedBuyData.Designer.cs b/ReallifeGamemode.Database/Migrations/20210527144901_AddUserCannabisSeedBuyData.Designer.cs new file mode 100644 index 00000000..6f55b056 --- /dev/null +++ b/ReallifeGamemode.Database/Migrations/20210527144901_AddUserCannabisSeedBuyData.Designer.cs @@ -0,0 +1,2229 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using ReallifeGamemode.Database.Models; + +namespace ReallifeGamemode.Database.Migrations +{ + [DbContext(typeof(DatabaseContext))] + [Migration("20210527144901_AddUserCannabisSeedBuyData")] + partial class AddUserCannabisSeedBuyData + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.3") + .HasAnnotation("PropertyAccessMode", PropertyAccessMode.PreferFieldDuringConstruction) + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.ATM", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("Balance") + .HasColumnType("int"); + + b.Property("Faulty") + .HasColumnType("tinyint(1)"); + + b.Property("X") + .HasColumnType("float"); + + b.Property("Y") + .HasColumnType("float"); + + b.Property("Z") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.ToTable("ATMs"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.Ban", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Applied") + .HasColumnType("int"); + + b.Property("BannedBy") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Reason") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("UntilDateTime") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Bans"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.BusRoute", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Description") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.ToTable("BusRoutes"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.BusRoutePoint", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("BusRouteId") + .HasColumnType("int"); + + b.Property("Description") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("X") + .HasColumnType("float"); + + b.Property("Y") + .HasColumnType("float"); + + b.Property("Z") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.HasIndex("BusRouteId"); + + b.ToTable("BusRoutesPoints"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.BusinessBankAccount", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Balance") + .HasColumnType("int"); + + b.Property("BusinessId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("BusinessId") + .IsUnique(); + + b.ToTable("BusinessBankAccounts"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.BusinessData", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("BusinessId") + .HasColumnType("int"); + + b.Property("Price") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("BusinessData"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.CannabisPlant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("Harvested") + .HasColumnType("tinyint(1)"); + + b.Property("PlantDate") + .HasColumnType("datetime(6)"); + + b.Property("PlantedById") + .HasColumnType("int"); + + b.Property("X") + .HasColumnType("float"); + + b.Property("Y") + .HasColumnType("float"); + + b.Property("Z") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.HasIndex("PlantedById"); + + b.ToTable("CannabisPlants"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.Character", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Ageing") + .HasColumnType("tinyint unsigned"); + + b.Property("AgeingOpacity") + .HasColumnType("float"); + + b.Property("BeardColor") + .HasColumnType("tinyint unsigned"); + + b.Property("Blemishes") + .HasColumnType("tinyint unsigned"); + + b.Property("BlemishesOpacity") + .HasColumnType("float"); + + b.Property("Blush") + .HasColumnType("tinyint unsigned"); + + b.Property("BlushColor") + .HasColumnType("tinyint unsigned"); + + b.Property("BlushOpacity") + .HasColumnType("float"); + + b.Property("BrowDepth") + .HasColumnType("float"); + + b.Property("BrowHeight") + .HasColumnType("float"); + + b.Property("CheekDepth") + .HasColumnType("float"); + + b.Property("CheekboneHeight") + .HasColumnType("float"); + + b.Property("CheekboneWidth") + .HasColumnType("float"); + + b.Property("ChestHair") + .HasColumnType("tinyint unsigned"); + + b.Property("ChestHairColor") + .HasColumnType("tinyint unsigned"); + + b.Property("ChestHairOpacity") + .HasColumnType("float"); + + b.Property("ChinDepth") + .HasColumnType("float"); + + b.Property("ChinHeight") + .HasColumnType("float"); + + b.Property("ChinIndent") + .HasColumnType("float"); + + b.Property("ChinWidth") + .HasColumnType("float"); + + b.Property("Complexion") + .HasColumnType("tinyint unsigned"); + + b.Property("ComplexionOpacity") + .HasColumnType("float"); + + b.Property("EyeColor") + .HasColumnType("tinyint unsigned"); + + b.Property("EyeSize") + .HasColumnType("float"); + + b.Property("EyebrowColor") + .HasColumnType("tinyint unsigned"); + + b.Property("Eyebrows") + .HasColumnType("tinyint unsigned"); + + b.Property("EyebrowsOpacity") + .HasColumnType("float"); + + b.Property("FacialHair") + .HasColumnType("tinyint unsigned"); + + b.Property("FacialHairOpacity") + .HasColumnType("float"); + + b.Property("Father") + .HasColumnType("tinyint unsigned"); + + b.Property("Freckles") + .HasColumnType("tinyint unsigned"); + + b.Property("FrecklesOpacity") + .HasColumnType("float"); + + b.Property("Gender") + .HasColumnType("tinyint(1)"); + + b.Property("Hair") + .HasColumnType("tinyint unsigned"); + + b.Property("HairColor") + .HasColumnType("tinyint unsigned"); + + b.Property("HairHighlightColor") + .HasColumnType("tinyint unsigned"); + + b.Property("JawShape") + .HasColumnType("float"); + + b.Property("JawWidth") + .HasColumnType("float"); + + b.Property("LipThickness") + .HasColumnType("float"); + + b.Property("Lipstick") + .HasColumnType("tinyint unsigned"); + + b.Property("LipstickColor") + .HasColumnType("tinyint unsigned"); + + b.Property("LipstickOpacity") + .HasColumnType("float"); + + b.Property("Makeup") + .HasColumnType("tinyint unsigned"); + + b.Property("MakeupOpacity") + .HasColumnType("float"); + + b.Property("Mother") + .HasColumnType("tinyint unsigned"); + + b.Property("NeckWidth") + .HasColumnType("float"); + + b.Property("NoseBottomHeight") + .HasColumnType("float"); + + b.Property("NoseBridgeDepth") + .HasColumnType("float"); + + b.Property("NoseBroken") + .HasColumnType("float"); + + b.Property("NoseTipHeight") + .HasColumnType("float"); + + b.Property("NoseTipLength") + .HasColumnType("float"); + + b.Property("NoseWidth") + .HasColumnType("float"); + + b.Property("Similarity") + .HasColumnType("float"); + + b.Property("SkinSimilarity") + .HasColumnType("float"); + + b.Property("SunDamage") + .HasColumnType("tinyint unsigned"); + + b.Property("SunDamageOpacity") + .HasColumnType("float"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Characters"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.CharacterCloth", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ClothId") + .HasColumnType("int"); + + b.Property("Duty") + .HasColumnType("tinyint(1)"); + + b.Property("SlotId") + .HasColumnType("int"); + + b.Property("SlotType") + .HasColumnType("tinyint unsigned"); + + b.Property("Texture") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("CharacterClothes"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.ClothCombination", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Gender") + .HasColumnType("tinyint(1)"); + + b.Property("Top") + .HasColumnType("int"); + + b.Property("Torso") + .HasColumnType("int"); + + b.Property("Undershirt") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("ClothCombinations"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.Door", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AlwaysOpen") + .HasColumnType("tinyint(1)"); + + b.Property("Category") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("FactionId") + .HasColumnType("int"); + + b.Property("Locked") + .HasColumnType("tinyint(1)"); + + b.Property("Model") + .HasColumnType("int"); + + b.Property("Name") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Radius") + .HasColumnType("float"); + + b.Property("X") + .HasColumnType("float"); + + b.Property("Y") + .HasColumnType("float"); + + b.Property("Z") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.HasIndex("FactionId"); + + b.ToTable("Doors"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.DutyCloth", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ClothId") + .HasColumnType("int"); + + b.Property("FactionId") + .HasColumnType("int"); + + b.Property("Gender") + .HasColumnType("tinyint(1)"); + + b.Property("SlotId") + .HasColumnType("int"); + + b.Property("SlotType") + .HasColumnType("tinyint unsigned"); + + b.HasKey("Id"); + + b.HasIndex("FactionId"); + + b.ToTable("DutyClothes"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.Faction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("BankAccountId") + .HasColumnType("int"); + + b.Property("GangOwned") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .HasColumnType("varchar(32) CHARACTER SET utf8mb4") + .HasMaxLength(32); + + b.Property("StateOwned") + .HasColumnType("tinyint(1)"); + + b.Property("WeaponDealTime") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("BankAccountId"); + + b.ToTable("Factions"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.FactionBankAccount", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("Balance") + .HasColumnType("int"); + + b.Property("Bic") + .HasColumnType("varchar(12) CHARACTER SET utf8mb4") + .HasMaxLength(12); + + b.Property("Iban") + .HasColumnType("varchar(32) CHARACTER SET utf8mb4") + .HasMaxLength(32); + + b.HasKey("Id"); + + b.ToTable("FactionBankAccounts"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.FactionRank", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("FactionId") + .HasColumnType("int"); + + b.Property("Order") + .HasColumnType("int"); + + b.Property("RankName") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("FactionId"); + + b.ToTable("FactionRanks"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.FactionWeapon", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Ammount") + .HasColumnType("int"); + + b.Property("FactionId") + .HasColumnType("int"); + + b.Property("Rank") + .HasColumnType("int"); + + b.Property("SlotID") + .HasColumnType("int"); + + b.Property("WeaponModel") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("FactionId"); + + b.ToTable("FactionWeapons"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.GotoPoint", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("Description") + .HasColumnType("varchar(32) CHARACTER SET utf8mb4") + .HasMaxLength(32); + + b.Property("X") + .HasColumnType("float"); + + b.Property("Y") + .HasColumnType("float"); + + b.Property("Z") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.ToTable("GotoPoints"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.Group", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("BankAccountId") + .HasColumnType("int"); + + b.Property("Name") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("BankAccountId"); + + b.ToTable("Groups"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.GroupBankAccount", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Balance") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("GroupBankAccounts"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.House", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("BankAccountId") + .HasColumnType("int"); + + b.Property("CanRentIn") + .HasColumnType("tinyint(1)"); + + b.Property("LastRentSetTime") + .HasColumnType("datetime(6)"); + + b.Property("OwnerId") + .HasColumnType("int"); + + b.Property("Price") + .HasColumnType("int"); + + b.Property("RentalFee") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("X") + .HasColumnType("float"); + + b.Property("Y") + .HasColumnType("float"); + + b.Property("Z") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.HasIndex("BankAccountId"); + + b.HasIndex("OwnerId"); + + b.ToTable("Houses"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.HouseBankAccount", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Balance") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("HouseBankAccounts"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.HouseRental", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("HouseId") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("HouseId"); + + b.HasIndex("UserId"); + + b.ToTable("HouseRentals"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.Interior", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("EnterPositionStr") + .HasColumnName("EnterPosition") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("ExitPositionStr") + .HasColumnName("ExitPosition") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Name") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.ToTable("Interiors"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.Location", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Description") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Heading") + .HasColumnType("double"); + + b.Property("X") + .HasColumnType("double"); + + b.Property("Y") + .HasColumnType("double"); + + b.Property("Z") + .HasColumnType("double"); + + b.HasKey("Id"); + + b.ToTable("Locations"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.Logs.BankAccountTransactionHistory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Fee") + .HasColumnType("int"); + + b.Property("MoneySent") + .HasColumnType("int"); + + b.Property("NewReceiverBalance") + .HasColumnType("int"); + + b.Property("NewSenderBalance") + .HasColumnType("int"); + + b.Property("Origin") + .HasColumnType("varchar(32) CHARACTER SET utf8mb4") + .HasMaxLength(32); + + b.Property("Receiver") + .HasColumnType("varchar(32) CHARACTER SET utf8mb4") + .HasMaxLength(32); + + b.Property("ReceiverBalance") + .HasColumnType("int"); + + b.Property("Sender") + .HasColumnType("varchar(32) CHARACTER SET utf8mb4") + .HasMaxLength(32); + + b.Property("SenderBalance") + .HasColumnType("int"); + + b.Property("Timestamp") + .ValueGeneratedOnAdd() + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.ToTable("BankAccountTransactionLogs"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.Logs.Chat.ChatLogEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("Discriminator") + .IsRequired() + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Text") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Time") + .ValueGeneratedOnAdd() + .HasColumnType("datetime(6)"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("ChatLogs"); + + b.HasDiscriminator("Discriminator").HasValue("ChatLogEntry"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.Logs.CommandLogEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("Command") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Time") + .HasColumnType("datetime(6)"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("CommandLogs"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.Logs.Death", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CauseOfDeath") + .HasColumnType("varchar(64) CHARACTER SET utf8mb4") + .HasMaxLength(64); + + b.Property("KillerHeading") + .HasColumnType("float"); + + b.Property("KillerId") + .HasColumnType("int"); + + b.Property("KillerPositionX") + .HasColumnType("float"); + + b.Property("KillerPositionY") + .HasColumnType("float"); + + b.Property("KillerPositionZ") + .HasColumnType("float"); + + b.Property("Timestamp") + .ValueGeneratedOnAdd() + .HasColumnType("datetime(6)"); + + b.Property("VictimHeading") + .HasColumnType("float"); + + b.Property("VictimId") + .HasColumnType("int"); + + b.Property("VictimPositionX") + .HasColumnType("float"); + + b.Property("VictimPositionY") + .HasColumnType("float"); + + b.Property("VictimPositionZ") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.HasIndex("KillerId"); + + b.HasIndex("VictimId"); + + b.ToTable("DeathLogs"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.Logs.LoginLogoutLogEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("IpAddress") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("LoginLogout") + .HasColumnType("tinyint(1)"); + + b.Property("PlayerId") + .HasColumnType("bigint"); + + b.Property("SocialClubName") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Time") + .HasColumnType("datetime(6)"); + + b.Property("UserId") + .HasColumnType("int"); + + b.Property("Username") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("LoginLogoutLogs"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.News", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("Caption") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Content") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Timestamp") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("News"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.Saves.SavedBlip", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("Alpha") + .HasColumnType("tinyint unsigned"); + + b.Property("Color") + .HasColumnType("tinyint unsigned"); + + b.Property("Dimension") + .HasColumnType("tinyint unsigned"); + + b.Property("DrawDistance") + .HasColumnType("float"); + + b.Property("Name") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("PositionX") + .HasColumnType("float"); + + b.Property("PositionY") + .HasColumnType("float"); + + b.Property("PositionZ") + .HasColumnType("float"); + + b.Property("Rotation") + .HasColumnType("float"); + + b.Property("Scale") + .HasColumnType("float"); + + b.Property("ShortRange") + .HasColumnType("tinyint(1)"); + + b.Property("Sprite") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.ToTable("Blips"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.Saves.SavedMarker", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("ColorA") + .HasColumnType("tinyint unsigned"); + + b.Property("ColorB") + .HasColumnType("tinyint unsigned"); + + b.Property("ColorG") + .HasColumnType("tinyint unsigned"); + + b.Property("ColorR") + .HasColumnType("tinyint unsigned"); + + b.Property("Dimension") + .HasColumnType("tinyint unsigned"); + + b.Property("DirectionX") + .HasColumnType("float"); + + b.Property("DirectionY") + .HasColumnType("float"); + + b.Property("DirectionZ") + .HasColumnType("float"); + + b.Property("PositionX") + .HasColumnType("float"); + + b.Property("PositionY") + .HasColumnType("float"); + + b.Property("PositionZ") + .HasColumnType("float"); + + b.Property("RotationX") + .HasColumnType("float"); + + b.Property("RotationY") + .HasColumnType("float"); + + b.Property("RotationZ") + .HasColumnType("float"); + + b.Property("Scale") + .HasColumnType("float"); + + b.Property("Type") + .HasColumnType("tinyint unsigned"); + + b.Property("Visible") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.ToTable("Markers"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.Saves.SavedPed", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("Dimension") + .HasColumnType("tinyint unsigned"); + + b.Property("HashModel") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Heading") + .HasColumnType("float"); + + b.Property("PositionX") + .HasColumnType("float"); + + b.Property("PositionY") + .HasColumnType("float"); + + b.Property("PositionZ") + .HasColumnType("float"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("Peds"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.Saves.SavedPickup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("Dimension") + .HasColumnType("tinyint unsigned"); + + b.Property("PositionX") + .HasColumnType("float") + .HasMaxLength(128); + + b.Property("PositionY") + .HasColumnType("float"); + + b.Property("PositionZ") + .HasColumnType("float"); + + b.Property("RespawnTime") + .HasColumnType("int"); + + b.Property("RotationX") + .HasColumnType("float"); + + b.Property("RotationY") + .HasColumnType("float"); + + b.Property("RotationZ") + .HasColumnType("float"); + + b.Property("Vehicle") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.ToTable("Pickups"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.Saves.SavedTextLabel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("ColorA") + .HasColumnType("tinyint unsigned"); + + b.Property("ColorB") + .HasColumnType("tinyint unsigned"); + + b.Property("ColorG") + .HasColumnType("tinyint unsigned"); + + b.Property("ColorR") + .HasColumnType("tinyint unsigned"); + + b.Property("Dimension") + .HasColumnType("tinyint unsigned"); + + b.Property("DrawDistance") + .HasColumnType("float"); + + b.Property("Font") + .HasColumnType("tinyint unsigned"); + + b.Property("LOS") + .HasColumnType("tinyint(1)"); + + b.Property("PositionX") + .HasColumnType("float"); + + b.Property("PositionY") + .HasColumnType("float"); + + b.Property("PositionZ") + .HasColumnType("float"); + + b.Property("Text") + .IsRequired() + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.ToTable("TextLabels"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.ServerVariable", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Value") + .HasColumnType("int"); + + b.Property("Variable") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.ToTable("ServerVariables"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.ServerVehicle", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(true); + + b.Property("Discriminator") + .IsRequired() + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("DistanceDriven") + .HasColumnType("float"); + + b.Property("Heading") + .HasColumnType("float"); + + b.Property("Livery") + .HasColumnType("int"); + + b.Property("Locked") + .HasColumnType("tinyint(1)"); + + b.Property("Model") + .HasColumnType("int unsigned"); + + b.Property("NumberPlate") + .HasColumnType("varchar(8) CHARACTER SET utf8mb4") + .HasMaxLength(8); + + b.Property("PositionX") + .HasColumnType("float"); + + b.Property("PositionY") + .HasColumnType("float"); + + b.Property("PositionZ") + .HasColumnType("float"); + + b.Property("PrimaryColor") + .HasColumnType("int"); + + b.Property("SecondaryColor") + .HasColumnType("int"); + + b.Property("TankAmount") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.ToTable("ServerVehicles"); + + b.HasDiscriminator("Discriminator").HasValue("ServerVehicle"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.ShopClothe", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Category") + .HasColumnType("int"); + + b.Property("ClotheId") + .HasColumnType("int"); + + b.Property("ComponentId") + .HasColumnType("int"); + + b.Property("Gender") + .HasColumnType("tinyint(1)"); + + b.Property("Price") + .HasColumnType("int"); + + b.Property("TypeId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.ToTable("ShopClothes"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.ShopItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Amount") + .HasColumnType("int"); + + b.Property("ItemId") + .HasColumnType("int"); + + b.Property("Price") + .HasColumnType("int"); + + b.Property("ShopId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("ShopItems"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.TuningGarage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("X") + .HasColumnType("float"); + + b.Property("Y") + .HasColumnType("float"); + + b.Property("Z") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.ToTable("TuningGarages"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.Turfs", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Color") + .HasColumnType("int"); + + b.Property("FactionId") + .HasColumnType("int"); + + b.Property("MaxValue") + .HasColumnType("int"); + + b.Property("Name") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Owner") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Range") + .HasColumnType("float"); + + b.Property("Rotation") + .HasColumnType("float"); + + b.Property("Surplus") + .HasColumnType("tinyint(1)"); + + b.Property("Value") + .HasColumnType("int"); + + b.Property("Vector") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("X") + .HasColumnType("float"); + + b.Property("Y") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.ToTable("Turfs"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AdminLevel") + .HasColumnType("int"); + + b.Property("BanId") + .HasColumnType("int"); + + b.Property("BankAccountId") + .HasColumnType("int"); + + b.Property("BusSkill") + .HasColumnType("int"); + + b.Property("BusinessId") + .HasColumnType("int"); + + b.Property("CannabisSeedsBoughtToday") + .HasColumnType("int"); + + b.Property("CharacterId") + .HasColumnType("int"); + + b.Property("Dead") + .HasColumnType("tinyint(1)"); + + b.Property("DriverLicenseBike") + .HasColumnType("tinyint(1)"); + + b.Property("DriverLicenseVehicle") + .HasColumnType("tinyint(1)"); + + b.Property("Email") + .HasColumnType("varchar(64) CHARACTER SET utf8mb4") + .HasMaxLength(64); + + b.Property("FactionId") + .HasColumnType("int"); + + b.Property("FactionLeader") + .HasColumnType("tinyint(1)"); + + b.Property("FactionRankId") + .HasColumnType("int"); + + b.Property("FlyingLicensePlane") + .HasColumnType("tinyint(1)"); + + b.Property("FreeSurgery") + .HasColumnType("tinyint(1)"); + + b.Property("GroupId") + .HasColumnType("int"); + + b.Property("GroupRank") + .HasColumnType("int"); + + b.Property("Handmoney") + .HasColumnType("int"); + + b.Property("HouseId") + .HasColumnType("int"); + + b.Property("JailTime") + .HasColumnType("int"); + + b.Property("JobId") + .HasColumnType("int"); + + b.Property("LastTimeBoughtCannabisSeeds") + .HasColumnType("datetime(6)"); + + b.Property("LogUserId") + .HasColumnType("int"); + + b.Property("Name") + .HasColumnType("varchar(32) CHARACTER SET utf8mb4") + .HasMaxLength(32); + + b.Property("Password") + .HasColumnType("varchar(64) CHARACTER SET utf8mb4") + .HasMaxLength(64); + + b.Property("PaydayTimer") + .HasColumnType("int"); + + b.Property("PilotSkill") + .HasColumnType("int"); + + b.Property("PlayedMinutes") + .HasColumnType("int"); + + b.Property("Points") + .HasColumnType("int"); + + b.Property("PositionX") + .HasColumnType("float"); + + b.Property("PositionY") + .HasColumnType("float"); + + b.Property("PositionZ") + .HasColumnType("float"); + + b.Property("RegistrationDate") + .ValueGeneratedOnAdd() + .HasColumnType("datetime(6)"); + + b.Property("SocialClubName") + .HasColumnType("varchar(32) CHARACTER SET utf8mb4") + .HasMaxLength(32); + + b.Property("Wage") + .HasColumnType("int"); + + b.Property("Wanteds") + .HasColumnType("int"); + + b.Property("WeaponLicense") + .HasColumnType("tinyint(1)"); + + b.Property("failpoints") + .HasColumnType("int"); + + b.Property("otheramount") + .HasColumnType("int"); + + b.Property("trashcount") + .HasColumnType("int"); + + b.Property("warn") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("BanId"); + + b.HasIndex("BankAccountId"); + + b.HasIndex("BusinessId") + .IsUnique(); + + b.HasIndex("CharacterId"); + + b.HasIndex("FactionId"); + + b.HasIndex("FactionRankId"); + + b.HasIndex("GroupId"); + + b.HasIndex("HouseId"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.UserBankAccount", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("Balance") + .HasColumnType("int"); + + b.Property("Bic") + .HasColumnType("varchar(12) CHARACTER SET utf8mb4") + .HasMaxLength(12); + + b.Property("Iban") + .HasColumnType("varchar(32) CHARACTER SET utf8mb4") + .HasMaxLength(32); + + b.HasKey("Id"); + + b.ToTable("UserBankAccounts"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.UserItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Amount") + .HasColumnType("int"); + + b.Property("ItemId") + .HasColumnType("int"); + + b.Property("Slot") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserItems"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.UserWeapon", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Ammo") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("int"); + + b.Property("WeaponId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.HasIndex("WeaponId"); + + b.ToTable("UserWeapons"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.VehicleItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Amount") + .HasColumnType("int"); + + b.Property("ItemId") + .HasColumnType("int"); + + b.Property("Slot") + .HasColumnType("int"); + + b.Property("VehicleId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("VehicleId"); + + b.ToTable("VehicleItems"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.VehicleMod", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ModId") + .HasColumnType("int"); + + b.Property("ServerVehicleId") + .HasColumnType("int"); + + b.Property("Slot") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ServerVehicleId", "Slot") + .IsUnique(); + + b.ToTable("VehicleMods"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.Weapon", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Ammo") + .HasColumnType("int"); + + b.Property("AmmunationActive") + .HasColumnType("tinyint(1)"); + + b.Property("CategoryId") + .HasColumnType("int"); + + b.Property("Legal") + .HasColumnType("tinyint(1)"); + + b.Property("Price") + .HasColumnType("float"); + + b.Property("SlotID") + .HasColumnType("int"); + + b.Property("WeaponModel") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("CategoryId"); + + b.ToTable("Weapons"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.WeaponCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Category") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.ToTable("WeaponCategories"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.Whitelist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("SocialClubName") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.ToTable("WhitelistEntries"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.Logs.Chat.DepartmentChatLogEntry", b => + { + b.HasBaseType("ReallifeGamemode.Database.Entities.Logs.Chat.ChatLogEntry"); + + b.HasDiscriminator().HasValue("DepartmentChatLogEntry"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.Logs.Chat.FactionChatLogEntry", b => + { + b.HasBaseType("ReallifeGamemode.Database.Entities.Logs.Chat.ChatLogEntry"); + + b.Property("FactionId") + .HasColumnType("int"); + + b.HasIndex("FactionId"); + + b.HasDiscriminator().HasValue("FactionChatLogEntry"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.Logs.Chat.GangChatLogEntry", b => + { + b.HasBaseType("ReallifeGamemode.Database.Entities.Logs.Chat.ChatLogEntry"); + + b.HasDiscriminator().HasValue("GangChatLogEntry"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.Logs.Chat.GroupChatLogEntry", b => + { + b.HasBaseType("ReallifeGamemode.Database.Entities.Logs.Chat.ChatLogEntry"); + + b.Property("GroupId") + .HasColumnType("int"); + + b.HasIndex("GroupId"); + + b.HasDiscriminator().HasValue("GroupChatLogEntry"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.Logs.Chat.LeaderChatLogEntry", b => + { + b.HasBaseType("ReallifeGamemode.Database.Entities.Logs.Chat.ChatLogEntry"); + + b.HasDiscriminator().HasValue("LeaderChatLogEntry"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.Logs.Chat.LocalChatLogEntry", b => + { + b.HasBaseType("ReallifeGamemode.Database.Entities.Logs.Chat.ChatLogEntry"); + + b.HasDiscriminator().HasValue("LocalChatLogEntry"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.Logs.Chat.NewsChatLogEntry", b => + { + b.HasBaseType("ReallifeGamemode.Database.Entities.Logs.Chat.ChatLogEntry"); + + b.HasDiscriminator().HasValue("NewsChatLogEntry"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.Logs.Chat.OChatLogEntry", b => + { + b.HasBaseType("ReallifeGamemode.Database.Entities.Logs.Chat.ChatLogEntry"); + + b.HasDiscriminator().HasValue("OChatLogEntry"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.FactionVehicle", b => + { + b.HasBaseType("ReallifeGamemode.Database.Entities.ServerVehicle"); + + b.Property("BuyPrice") + .HasColumnType("int"); + + b.Property("Owners") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.ToTable("FactionVehicles"); + + b.HasDiscriminator().HasValue("FactionVehicle"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.GroupVehicle", b => + { + b.HasBaseType("ReallifeGamemode.Database.Entities.ServerVehicle"); + + b.Property("GroupId") + .HasColumnType("int"); + + b.HasIndex("GroupId"); + + b.HasDiscriminator().HasValue("GroupVehicle"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.JobVehicle", b => + { + b.HasBaseType("ReallifeGamemode.Database.Entities.ServerVehicle"); + + b.Property("JobId") + .HasColumnType("int"); + + b.HasDiscriminator().HasValue("JobVehicle"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.NoobSpawnVehicle", b => + { + b.HasBaseType("ReallifeGamemode.Database.Entities.ServerVehicle"); + + b.HasDiscriminator().HasValue("NoobSpawnVehicle"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.NoobVehicle", b => + { + b.HasBaseType("ReallifeGamemode.Database.Entities.ServerVehicle"); + + b.HasDiscriminator().HasValue("NoobVehicle"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.Saves.SavedVehicle", b => + { + b.HasBaseType("ReallifeGamemode.Database.Entities.ServerVehicle"); + + b.HasDiscriminator().HasValue("SavedVehicle"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.SchoolVehicle", b => + { + b.HasBaseType("ReallifeGamemode.Database.Entities.ServerVehicle"); + + b.Property("SchoolId") + .HasColumnType("int"); + + b.HasDiscriminator().HasValue("SchoolVehicle"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.ShopVehicle", b => + { + b.HasBaseType("ReallifeGamemode.Database.Entities.ServerVehicle"); + + b.Property("BusinessId") + .HasColumnType("int"); + + b.Property("Price") + .HasColumnType("int"); + + b.ToTable("ShopVehicles"); + + b.HasDiscriminator().HasValue("ShopVehicle"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.UserVehicle", b => + { + b.HasBaseType("ReallifeGamemode.Database.Entities.ServerVehicle"); + + b.Property("BusinessId") + .HasColumnName("UserVehicle_BusinessId") + .HasColumnType("int"); + + b.Property("Price") + .HasColumnName("UserVehicle_Price") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasIndex("UserId"); + + b.ToTable("UserVehicles"); + + b.HasDiscriminator().HasValue("UserVehicle"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.Ban", b => + { + b.HasOne("ReallifeGamemode.Database.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.BusRoutePoint", b => + { + b.HasOne("ReallifeGamemode.Database.Entities.BusRoute", "BusRoute") + .WithMany("RoutePoints") + .HasForeignKey("BusRouteId"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.CannabisPlant", b => + { + b.HasOne("ReallifeGamemode.Database.Entities.User", "PlantedBy") + .WithMany() + .HasForeignKey("PlantedById") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.Character", b => + { + b.HasOne("ReallifeGamemode.Database.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.CharacterCloth", b => + { + b.HasOne("ReallifeGamemode.Database.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.Door", b => + { + b.HasOne("ReallifeGamemode.Database.Entities.Faction", "Faction") + .WithMany() + .HasForeignKey("FactionId"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.DutyCloth", b => + { + b.HasOne("ReallifeGamemode.Database.Entities.Faction", "Faction") + .WithMany() + .HasForeignKey("FactionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.Faction", b => + { + b.HasOne("ReallifeGamemode.Database.Entities.FactionBankAccount", "BankAccount") + .WithMany() + .HasForeignKey("BankAccountId"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.FactionRank", b => + { + b.HasOne("ReallifeGamemode.Database.Entities.Faction", "Faction") + .WithMany() + .HasForeignKey("FactionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.FactionWeapon", b => + { + b.HasOne("ReallifeGamemode.Database.Entities.Faction", "Faction") + .WithMany() + .HasForeignKey("FactionId"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.Group", b => + { + b.HasOne("ReallifeGamemode.Database.Entities.GroupBankAccount", "BankAccount") + .WithMany() + .HasForeignKey("BankAccountId"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.House", b => + { + b.HasOne("ReallifeGamemode.Database.Entities.HouseBankAccount", "BankAccount") + .WithMany() + .HasForeignKey("BankAccountId"); + + b.HasOne("ReallifeGamemode.Database.Entities.User", "Owner") + .WithMany() + .HasForeignKey("OwnerId"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.HouseRental", b => + { + b.HasOne("ReallifeGamemode.Database.Entities.House", "House") + .WithMany("Rentals") + .HasForeignKey("HouseId"); + + b.HasOne("ReallifeGamemode.Database.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.Logs.Chat.ChatLogEntry", b => + { + b.HasOne("ReallifeGamemode.Database.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.Logs.CommandLogEntry", b => + { + b.HasOne("ReallifeGamemode.Database.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.Logs.Death", b => + { + b.HasOne("ReallifeGamemode.Database.Entities.User", "Killer") + .WithMany() + .HasForeignKey("KillerId"); + + b.HasOne("ReallifeGamemode.Database.Entities.User", "Victim") + .WithMany() + .HasForeignKey("VictimId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.Logs.LoginLogoutLogEntry", b => + { + b.HasOne("ReallifeGamemode.Database.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.News", b => + { + b.HasOne("ReallifeGamemode.Database.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.User", b => + { + b.HasOne("ReallifeGamemode.Database.Entities.Ban", "Ban") + .WithMany() + .HasForeignKey("BanId"); + + b.HasOne("ReallifeGamemode.Database.Entities.UserBankAccount", "BankAccount") + .WithMany() + .HasForeignKey("BankAccountId"); + + b.HasOne("ReallifeGamemode.Database.Entities.Character", "Character") + .WithMany() + .HasForeignKey("CharacterId"); + + b.HasOne("ReallifeGamemode.Database.Entities.Faction", "Faction") + .WithMany() + .HasForeignKey("FactionId"); + + b.HasOne("ReallifeGamemode.Database.Entities.FactionRank", "FactionRank") + .WithMany() + .HasForeignKey("FactionRankId"); + + b.HasOne("ReallifeGamemode.Database.Entities.Group", "Group") + .WithMany() + .HasForeignKey("GroupId"); + + b.HasOne("ReallifeGamemode.Database.Entities.House", "House") + .WithMany() + .HasForeignKey("HouseId"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.UserItem", b => + { + b.HasOne("ReallifeGamemode.Database.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.UserWeapon", b => + { + b.HasOne("ReallifeGamemode.Database.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ReallifeGamemode.Database.Entities.Weapon", "Weapon") + .WithMany() + .HasForeignKey("WeaponId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.VehicleItem", b => + { + b.HasOne("ReallifeGamemode.Database.Entities.ServerVehicle", "Vehicle") + .WithMany() + .HasForeignKey("VehicleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.VehicleMod", b => + { + b.HasOne("ReallifeGamemode.Database.Entities.ServerVehicle", "Vehicle") + .WithMany() + .HasForeignKey("ServerVehicleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.Weapon", b => + { + b.HasOne("ReallifeGamemode.Database.Entities.WeaponCategory", "WeaponCategory") + .WithMany() + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.Logs.Chat.FactionChatLogEntry", b => + { + b.HasOne("ReallifeGamemode.Database.Entities.Faction", "Faction") + .WithMany() + .HasForeignKey("FactionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.Logs.Chat.GroupChatLogEntry", b => + { + b.HasOne("ReallifeGamemode.Database.Entities.Group", "Group") + .WithMany() + .HasForeignKey("GroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.GroupVehicle", b => + { + b.HasOne("ReallifeGamemode.Database.Entities.Group", "Group") + .WithMany() + .HasForeignKey("GroupId"); + }); + + modelBuilder.Entity("ReallifeGamemode.Database.Entities.UserVehicle", b => + { + b.HasOne("ReallifeGamemode.Database.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/ReallifeGamemode.Database/Migrations/20210527144901_AddUserCannabisSeedBuyData.cs b/ReallifeGamemode.Database/Migrations/20210527144901_AddUserCannabisSeedBuyData.cs new file mode 100644 index 00000000..bc63b452 --- /dev/null +++ b/ReallifeGamemode.Database/Migrations/20210527144901_AddUserCannabisSeedBuyData.cs @@ -0,0 +1,33 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace ReallifeGamemode.Database.Migrations +{ + public partial class AddUserCannabisSeedBuyData : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "CannabisSeedsBoughtToday", + table: "Users", + nullable: false, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "LastTimeBoughtCannabisSeeds", + table: "Users", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "CannabisSeedsBoughtToday", + table: "Users"); + + migrationBuilder.DropColumn( + name: "LastTimeBoughtCannabisSeeds", + table: "Users"); + } + } +} diff --git a/ReallifeGamemode.Database/Migrations/DatabaseContextModelSnapshot.cs b/ReallifeGamemode.Database/Migrations/DatabaseContextModelSnapshot.cs index ceeeb6b5..ccb4e8cc 100644 --- a/ReallifeGamemode.Database/Migrations/DatabaseContextModelSnapshot.cs +++ b/ReallifeGamemode.Database/Migrations/DatabaseContextModelSnapshot.cs @@ -1456,6 +1456,9 @@ namespace ReallifeGamemode.Database.Migrations b.Property("BusinessId") .HasColumnType("int"); + b.Property("CannabisSeedsBoughtToday") + .HasColumnType("int"); + b.Property("CharacterId") .HasColumnType("int"); @@ -1505,6 +1508,9 @@ namespace ReallifeGamemode.Database.Migrations b.Property("JobId") .HasColumnType("int"); + b.Property("LastTimeBoughtCannabisSeeds") + .HasColumnType("datetime(6)"); + b.Property("LogUserId") .HasColumnType("int"); diff --git a/ReallifeGamemode.Server/BaseScript.cs b/ReallifeGamemode.Server/BaseScript.cs index 969ff10c..d9a27f6a 100644 --- a/ReallifeGamemode.Server/BaseScript.cs +++ b/ReallifeGamemode.Server/BaseScript.cs @@ -9,7 +9,7 @@ namespace ReallifeGamemode.Server { public abstract class BaseScript : Script { - protected readonly ILogger logger; + protected static ILogger logger { get; private set; } public BaseScript() { diff --git a/ReallifeGamemode.Server/Events/Death.cs b/ReallifeGamemode.Server/Events/Death.cs index 4c3a3637..697e2159 100644 --- a/ReallifeGamemode.Server/Events/Death.cs +++ b/ReallifeGamemode.Server/Events/Death.cs @@ -47,6 +47,14 @@ namespace ReallifeGamemode.Server.Events return; } + if(player.HasData("IsCarryingPlant") || player.GetData("IsCarryingPlant")) + { + var currentModel = player.GetData("HoldingCannabisPlant"); + + player.AddAttachment("CannabisPlantInHand" + currentModel, true); + player.ResetData("IsCarryingPlant"); + } + using var dbContext = new DatabaseContext(); User user = player.GetUser(dbContext); diff --git a/ReallifeGamemode.Server/Events/Disconnect.cs b/ReallifeGamemode.Server/Events/Disconnect.cs index ca1ba2ab..b8af1ce7 100644 --- a/ReallifeGamemode.Server/Events/Disconnect.cs +++ b/ReallifeGamemode.Server/Events/Disconnect.cs @@ -41,6 +41,14 @@ namespace ReallifeGamemode.Server.Events return; } + if (player.HasData("IsCarryingPlant") || player.GetData("IsCarryingPlant")) + { + var currentModel = player.GetData("HoldingCannabisPlant"); + + player.AddAttachment("CannabisPlantInHand" + currentModel, true); + player.ResetData("IsCarryingPlant"); + } + var logEntry = new LoginLogoutLogEntry() { LoginLogout = false, diff --git a/ReallifeGamemode.Server/Events/Key.cs b/ReallifeGamemode.Server/Events/Key.cs index 79274414..bf14ab2d 100644 --- a/ReallifeGamemode.Server/Events/Key.cs +++ b/ReallifeGamemode.Server/Events/Key.cs @@ -21,6 +21,8 @@ using ReallifeGamemode.Server.Types; using ReallifeGamemode.Server.Util; using ReallifeGamemode.Server.WeaponDeal; using ReallifeGamemode.Server.Log; +using ReallifeGamemode.Server.Inventory.Items; +using Microsoft.EntityFrameworkCore; using ReallifeGamemode.Server.Wanted; /** @@ -217,9 +219,61 @@ namespace ReallifeGamemode.Server.Events [RemoteEvent("keyPress:E")] public void KeyPressE(Player player) { - if (!player.IsLoggedIn() || player.GetData("isDead") || player.IsInVehicle) return; + if (!player.IsLoggedIn() || player.GetData("isDead")) return; var user = player.GetUser(); + if (player.IsInVehicle + && player.VehicleSeat == 0 + && player.Vehicle.Model == (uint)VehicleHash.Riot + && (user.FactionId == 1 || user.FactionId == 3) + && player.Position.DistanceTo(HanfManager.ASSERVATENKAMMER_POSITION) <= 3 + /*&& player.IsDuty()*/) + { + using var dbContext = new DatabaseContext(); + GTANetworkAPI.Vehicle veh = player.Vehicle; + ServerVehicle serverVehicle = veh.GetServerVehicle(dbContext); + + List items = InventoryManager.GetVehicleItems(veh); + if (items.Count() == 0) + { + player.SendNotification("Der Riot ist leer"); + return; + } + + IIllegalItem cannabisItem = InventoryManager.GetItem(); + IIllegalItem cannabisSeedItem = InventoryManager.GetItem(); + + VehicleItem vehicleCannabisItem = items.Where(i => i.ItemId == cannabisItem.Id).FirstOrDefault(); + VehicleItem vehicleCannabisSeedItem = items.Where(i => i.ItemId == cannabisSeedItem.Id).FirstOrDefault(); + + int cannabisAmount = vehicleCannabisItem?.Amount ?? 0; + int cannabisSeedAmount = vehicleCannabisSeedItem?.Amount ?? 0; + + InventoryManager.RemoveVehicleItem(serverVehicle, vehicleCannabisItem, cannabisAmount, player); + InventoryManager.RemoveVehicleItem(serverVehicle, vehicleCannabisSeedItem, cannabisSeedAmount, player); + + var price = cannabisSeedAmount * cannabisSeedItem.PriceForConfiscation + cannabisAmount * cannabisItem.PriceForConfiscation; + + logger.LogInformation("Player {0} unloaded the riot truck with {1} cannabis and {2} cannabis seed and the faction got {3}", player.Name, cannabisAmount, cannabisSeedAmount, price); + + var factions = dbContext.Factions.Include(f => f.BankAccount).Where(f => f.Id == 1 || f.Id == 3); + foreach (var faction in factions) + { + faction.BankAccount.Balance += price; + } + + player.SendNotification("~g~Der Riot wurde erfolgreich entladen"); + + dbContext.SaveChanges(); + + return; + } + + if (player.IsInVehicle) + { + return; + } + if (player.HasData("nearATM")) { ATMManager.ShowAtmUi(player, player.GetData("nearATM")); @@ -245,6 +299,7 @@ namespace ReallifeGamemode.Server.Events JailPoint nearestjailPoint = PositionManager.jailPoints.Find(s => s.Position.DistanceTo(player.Position) <= 1.5); bool isNearCannabisSeedBuyPoint = HanfManager.IsPlayerNearSeedBuyPoint(player); bool isNearJointManufacturerPoint = HanfManager.IsPlayerNearJointManufacturer(player); + bool isNearCannabisSellPoint = HanfManager.IsPlayerNearCannabisSellPoint(player); if (user?.FactionId != null) { @@ -766,7 +821,7 @@ namespace ReallifeGamemode.Server.Events if (isNearCannabisSeedBuyPoint) { - player.TriggerEvent("SERVER:Hanf_BuySeed", HanfManager.SEED_PRICE); + HanfManager.ShowPlayerBuySeedMenu(player); return; } @@ -775,6 +830,39 @@ namespace ReallifeGamemode.Server.Events HanfManager.BuildJointsFromCannabis(player); return; } + + if (isNearCannabisSellPoint) + { + HanfManager.PlayerSellCannabis(player); + return; + } + + if (player.HasData("IsCarryingPlant") || player.GetData("IsCarryingPlant") && (user.FactionId == 3 || user.FactionId == 1) && player.IsDuty()) + { + using var dbContext = new DatabaseContext(); + FactionVehicle riot = dbContext.FactionVehicles.Where(f => f.Model == VehicleHash.Riot).ToList().Where(f => f.GetOwners().Contains(3)).FirstOrDefault(); + if (riot == null) + { + return; + } + GTANetworkAPI.Vehicle riotVehicle = VehicleManager.GetVehicleFromServerVehicle(riot); + if (riotVehicle.Position.DistanceTo(player.Position) > 3) + { + return; + } + + var currentModel = player.GetData("HoldingCannabisPlant"); + + player.AddAttachment("CannabisPlantInHand" + currentModel, true); + player.ResetData("IsCarryingPlant"); + + var cannabisItem = InventoryManager.GetItem(); + var cannabisSeedsItem = InventoryManager.GetItem(); + int itemIdToGive = currentModel == 3 ? cannabisItem.Id : cannabisSeedsItem.Id; + int amountToGive = currentModel == 3 ? new Random().Next(4, 10) + 1 : 1; + + InventoryManager.AddItemToVehicleInventory(riotVehicle, itemIdToGive, amountToGive); + } } [RemoteEvent("keyPress:I")] diff --git a/ReallifeGamemode.Server/Events/Vehicle.cs b/ReallifeGamemode.Server/Events/Vehicle.cs index ff21e6d8..4be3db76 100644 --- a/ReallifeGamemode.Server/Events/Vehicle.cs +++ b/ReallifeGamemode.Server/Events/Vehicle.cs @@ -1,17 +1,21 @@ using System; using System.Linq; using GTANetworkAPI; +using Microsoft.Extensions.Logging; using ReallifeGamemode.Database.Entities; using ReallifeGamemode.Database.Models; using ReallifeGamemode.Server.Extensions; using ReallifeGamemode.Server.Types; using ReallifeGamemode.Server.Util; using ReallifeGamemode.Server.WeaponDeal; +using ReallifeGamemode.Server.Log; namespace ReallifeGamemode.Server.Events { public class Vehicle : Script { + private static readonly ILogger logger = LogManager.GetLogger(); + [RemoteEvent("VehicleMenu_ToggleEngine")] public void VehicleMenuToggleEngineEvent(Player player) { @@ -271,6 +275,8 @@ namespace ReallifeGamemode.Server.Events sV.PositionZ = pos.Z; sV.Heading = v.Heading; + logger.LogInformation("Player {0} parked the car {1} at x:{2}, y:{3}, z:{4}", player.Name, sV.Id, pos.X, pos.Y, pos.Z); + player.SendNotification("~g~Das Fahrzeug wurde geparkt."); diff --git a/ReallifeGamemode.Server/Inventory/Interfaces/IIllegalItem.cs b/ReallifeGamemode.Server/Inventory/Interfaces/IIllegalItem.cs new file mode 100644 index 00000000..caac39a5 --- /dev/null +++ b/ReallifeGamemode.Server/Inventory/Interfaces/IIllegalItem.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace ReallifeGamemode.Server.Inventory.Interfaces +{ + interface IIllegalItem : IItem + { + int PriceForConfiscation { get; } + } +} diff --git a/ReallifeGamemode.Server/Inventory/Items/Cannabis.cs b/ReallifeGamemode.Server/Inventory/Items/Cannabis.cs index bd82e7af..11f2c7bf 100644 --- a/ReallifeGamemode.Server/Inventory/Items/Cannabis.cs +++ b/ReallifeGamemode.Server/Inventory/Items/Cannabis.cs @@ -9,7 +9,7 @@ using ReallifeGamemode.Server.Inventory.Interfaces; namespace ReallifeGamemode.Server.Inventory.Items { - public class Cannabis : DropItem + public class Cannabis : DropItem, IIllegalItem { public override int Id => 108; @@ -24,5 +24,9 @@ namespace ReallifeGamemode.Server.Inventory.Items public override uint Object => 3076948544; public override int Price => 0; + + public override bool Legal => false; + + public int PriceForConfiscation { get; } = 5; } } diff --git a/ReallifeGamemode.Server/Inventory/Items/CannabisSeeds.cs b/ReallifeGamemode.Server/Inventory/Items/CannabisSeeds.cs index f3fa752d..7d3d098a 100644 --- a/ReallifeGamemode.Server/Inventory/Items/CannabisSeeds.cs +++ b/ReallifeGamemode.Server/Inventory/Items/CannabisSeeds.cs @@ -5,11 +5,12 @@ using GTANetworkAPI; using ReallifeGamemode.Database.Entities; using ReallifeGamemode.Database.Models; using ReallifeGamemode.Server.Extensions; +using ReallifeGamemode.Server.Inventory.Interfaces; using ReallifeGamemode.Server.Managers; namespace ReallifeGamemode.Server.Inventory.Items { - public class CannabisSeeds : UseItem + public class CannabisSeeds : UseItem, IIllegalItem { public override int Id { get; } = 109; public override string Name { get; } = "Cannabis Samen"; @@ -21,14 +22,15 @@ namespace ReallifeGamemode.Server.Inventory.Items public override uint Object { get; } public override bool RemoveWhenUsed { get; } = false; + public int PriceForConfiscation { get; } = 10; public override bool Use(Player player, User user, DatabaseContext databaseContext) { - if(!player.IsInVehicle) + if (!player.IsInVehicle) { HanfManager.StartCannabisPlanting(player); } - + return true; } } diff --git a/ReallifeGamemode.Server/Inventory/Items/Joint.cs b/ReallifeGamemode.Server/Inventory/Items/Joint.cs index 97ffc677..21ed6a6f 100644 --- a/ReallifeGamemode.Server/Inventory/Items/Joint.cs +++ b/ReallifeGamemode.Server/Inventory/Items/Joint.cs @@ -5,12 +5,16 @@ using GTANetworkAPI; using ReallifeGamemode.Database.Entities; using ReallifeGamemode.Database.Models; using ReallifeGamemode.Server.Extensions; +using ReallifeGamemode.Server.Inventory.Interfaces; using ReallifeGamemode.Server.Util; namespace ReallifeGamemode.Server.Inventory.Items { - public class Joint : UseItem + public class Joint : UseItem, IIllegalItem { + private static Dictionary lastJointUse = new Dictionary(); + private static readonly TimeSpan _jointCooldown = TimeSpan.FromMinutes(10); + public override int Id { get; } = 110; public override string Name { get; } = "Joint"; public override string Description { get; } = "stay high bis zum tod"; @@ -21,10 +25,33 @@ namespace ReallifeGamemode.Server.Inventory.Items public override bool Legal => false; public override bool RemoveWhenUsed => true; + public int PriceForConfiscation { get; } = 25; + public override bool Use(Player player, User user, DatabaseContext databaseContext) { + if (!CanUserUseJoint(user)) + { + player.TriggerEvent("Error", $"Versuche es nach {-1 * (int)((DateTime.Now - lastJointUse[user.Id]) - _jointCooldown).TotalSeconds} Sekunden erneut."); + return false; + } + + player.SyncAnimation("jointUse"); + player.ToggleInventory(InventoryToggleOption.HIDE); + int armorToSet = Math.Min(player.Armor + 25, 100); + player.SafeSetArmor(armorToSet); + lastJointUse[user.Id] = DateTime.Now; return true; } + + private bool CanUserUseJoint(User user) + { + if(!lastJointUse.ContainsKey(user.Id)) + { + return true; + } + + return DateTime.Now - lastJointUse[user.Id] > _jointCooldown; + } } } diff --git a/ReallifeGamemode.Server/Managers/HanfManager.cs b/ReallifeGamemode.Server/Managers/HanfManager.cs index fa1ffd2e..a2916668 100644 --- a/ReallifeGamemode.Server/Managers/HanfManager.cs +++ b/ReallifeGamemode.Server/Managers/HanfManager.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using System.Timers; using GTANetworkAPI; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using ReallifeGamemode.Database.Entities; @@ -12,6 +13,7 @@ using ReallifeGamemode.Server.Extensions; using ReallifeGamemode.Server.Inventory.Interfaces; using ReallifeGamemode.Server.Inventory.Items; using ReallifeGamemode.Server.Services; +using ReallifeGamemode.Server.Types; using ReallifeGamemode.Server.Util; namespace ReallifeGamemode.Server.Managers @@ -23,10 +25,28 @@ namespace ReallifeGamemode.Server.Managers /// private readonly static List _seedsBuyPoints = new List(); + private readonly static List _cannabisSellPoints = new List(); + /// /// Aktueller Samen-Preis /// - public static int SEED_PRICE = 50; + public static int SEED_PRICE = 0; + + private const int SEED_PRICE_MIN = 40; + private const int SEED_PRICE_MAX = 75; + + /// + /// Aktueller Hanf-Verkaufspreis + /// + public static int CANNABIS_PRICE = 0; + + private const int CANNABIS_PRICE_MIN = 50; + private const int CANNABIS_PRICE_MAX = 125; + + /// + /// Wie viele Samen ein Spieler pro Tag maximal kaufen darf + /// + private const int MAX_SEEDS_PER_DAY = 50; /// /// Wie viele Joints man aus einem Cannabis bekommt @@ -72,6 +92,8 @@ namespace ReallifeGamemode.Server.Managers private static List _currentCannabisData = new List(); + public static readonly Vector3 ASSERVATENKAMMER_POSITION = new Vector3(-5.45, -670.03, 32.33); + static HanfManager() { _manufacturerDoneTimer.Elapsed += ManufacturerDoneTimerCallback; @@ -82,6 +104,12 @@ namespace ReallifeGamemode.Server.Managers /// public static void Load() { + var priceRandom = new Random(); + + SEED_PRICE = priceRandom.Next(SEED_PRICE_MIN, SEED_PRICE_MAX + 1); + CANNABIS_PRICE = priceRandom.Next(CANNABIS_PRICE_MIN, CANNABIS_PRICE_MAX + 1); + logger.LogInformation("Generated hanf prices: seed = {0}, cannabis = {1}", SEED_PRICE, CANNABIS_PRICE); + _seedsBuyPoints.Add(new Vector3(-30.21876, -585.3222, 17.917326)); _seedsBuyPoints.Add(new Vector3(-680.89386, -634.6783, 25.29923)); _seedsBuyPoints.Add(new Vector3(-1310.743, -608.9064, 29.382874)); @@ -92,17 +120,58 @@ namespace ReallifeGamemode.Server.Managers foreach (Vector3 buyPoint in _seedsBuyPoints) { - colShape = NAPI.ColShape.CreateSphereColShape(buyPoint, 20.0f); + colShape = NAPI.ColShape.CreateSphereColShape(buyPoint, 10.0f); colShape.OnEntityEnterColShape += OnSeedBuyRangeColShapeEnter; } - UpdateHanfWorldData(new DatabaseContext()); + _cannabisSellPoints.Add(new Vector3(2220.04, 5614.24, 54.72)); + _cannabisSellPoints.Add(new Vector3(201.77, 2442.06, 60.45)); + _cannabisSellPoints.Add(new Vector3(155.87, -3103.26, 7.03)); + + foreach (Vector3 sellPoint in _cannabisSellPoints) + { + colShape = NAPI.ColShape.CreateSphereColShape(sellPoint, 10.0f); + colShape.OnEntityEnterColShape += OnCannabisSellRangeColShapeEnter; + } + + NAPI.Marker.CreateMarker(GTANetworkAPI.MarkerType.VerticalCylinder, ASSERVATENKAMMER_POSITION.Subtract(new Vector3(0, 0, 3.0)), new Vector3(), new Vector3(), 3.0f, Colors.White); + NAPI.TextLabel.CreateTextLabel("Asservatenkammer~n~Drücke ~y~E, um den ~y~Riot~s~ zu entladen", ASSERVATENKAMMER_POSITION, 10.0f, 10.0f, 0, Colors.White); + + using var dbContext = new DatabaseContext(); + HarvestRottenPlants(dbContext); + UpdateHanfWorldData(dbContext); Timer updateHanfDataTimer = new Timer(TimeSpan.FromMinutes(1).TotalMilliseconds); updateHanfDataTimer.Elapsed += UpdateHanfDataTimer_Elapsed; updateHanfDataTimer.Start(); } + private static void OnCannabisSellRangeColShapeEnter(ColShape colShape, Player player) + { + if (!player.IsLoggedIn()) + { + return; + } + + var user = player.GetUser(); + if (user?.Faction?.StateOwned == true) + { + return; + } + + ChatService.SendMessage(player, $"Fremder sagt: Pssst.. Hier kannst du dein Brokkoli loswerden."); + } + + private static void HarvestRottenPlants(DatabaseContext dbContext) + { + var rottenPlants = dbContext.CannabisPlants.Where(p => EF.Functions.DateDiffHour(p.PlantDate, DateTime.Now) > MAX_PLANT_TIME.TotalHours); + foreach (var plant in rottenPlants) + { + plant.Harvested = true; + } + dbContext.SaveChanges(); + } + private static void UpdateHanfDataTimer_Elapsed(object sender, ElapsedEventArgs e) { using var dbContext = new DatabaseContext(); @@ -148,7 +217,7 @@ namespace ReallifeGamemode.Server.Managers var user = player.GetUser(dbContext); if (user.Faction?.StateOwned ?? false) { - player.SendNotification("~r~Du darfst keine Hanfsamen einfplanzen"); + player.SendNotification("~r~Du darfst keine Hanfsamen einpflanzen"); return; } @@ -220,7 +289,7 @@ namespace ReallifeGamemode.Server.Managers public async static void UpdateHanfForPlayer(Player player, List cannabisData = null) { cannabisData ??= _currentCannabisData; - var x = await NAPI.Task.WaitForMainThread(); + await NAPI.Task.WaitForMainThread(); player.TriggerEvent("SERVER:Hanf_UpdateHanfData", JsonConvert.SerializeObject(cannabisData)); } @@ -235,6 +304,12 @@ namespace ReallifeGamemode.Server.Managers using var dbContext = new DatabaseContext(); var user = player.GetUser(dbContext); + if (amount > GetAmountOfCannabisSeedsPlayerCanBuyToday(user)) + { + player.SendNotification("~r~Du kannst heute nicht mehr so viele Samen kaufen"); + return; + } + IItem seedItem = InventoryManager.GetItem(); var newAmount = seedItem.Gewicht * amount; @@ -254,6 +329,16 @@ namespace ReallifeGamemode.Server.Managers logger.LogInformation("Player {0} bought {1} cannabis seeds for {2} dollars (price per seed: {3})", player.Name, amount, price, SEED_PRICE); // <-- WICHTIG LOGS + if (user.LastTimeBoughtCannabisSeeds == null || user.LastTimeBoughtCannabisSeeds.Value.Date != DateTime.Now.Date) + { + user.CannabisSeedsBoughtToday = amount; + } + else + { + user.CannabisSeedsBoughtToday += amount; + } + user.LastTimeBoughtCannabisSeeds = DateTime.Now; + user.Handmoney -= price; dbContext.SaveChanges(); @@ -263,7 +348,7 @@ namespace ReallifeGamemode.Server.Managers } [RemoteEvent("CLIENT:Hanf_HarvestHanf")] - public void HanfManagerHarvestHanf(Player player, long hanfId) + public async void HanfManagerHarvestHanf(Player player, long hanfId) { if (!player.IsLoggedIn()) { @@ -273,15 +358,10 @@ namespace ReallifeGamemode.Server.Managers using var dbContext = new DatabaseContext(); User user = player.GetUser(dbContext); - CannabisPlant plant = dbContext.CannabisPlants.Find(hanfId); + CannabisPlant plant = dbContext.CannabisPlants.Include(p => p.PlantedBy).Where(p => p.Id == hanfId).FirstOrDefault(); if (plant == null) { logger.LogError("Player {0} tried to harvest cannabis plant {1} but it was not found in database", player.Name, hanfId); - } - - if (user.Faction?.StateOwned == true && !(user.FactionId == 3 && player.IsDuty())) - { - player.SendNotification("~r~Du kannst kein Hanf ernten"); return; } @@ -290,10 +370,32 @@ namespace ReallifeGamemode.Server.Managers return; } - plant.Harvested = true; - - if (user.FactionId != 3) // Zivi / Gangmember erntet ab + if (player.IsAdminDuty() && player.IsTSupport() && user.IsAdmin(AdminLevel.ADMIN)) { + player.SendNotification($"Du hast die Hanf-Pflanze von ~y~{plant.PlantedBy.Name}~s~ entfernt"); + plant.Harvested = true; + dbContext.SaveChanges(); + UpdateHanfWorldData(dbContext); + return; + } + + if (user.Faction?.StateOwned == true) + { + if (!((user.FactionId == 1 || user.FactionId == 3) && player.IsDuty())) + { + player.SendNotification("~r~Du kannst kein Hanf ernten"); + return; + } + } + + //player.SyncAnimation(new[] { "harvestPlantEnter", "harvestPlant", "harvestPlantExit" }.ToList()); + //player.SyncAnimation("harvestPlant"); + //player.AddAttachment("shovel", false); + + if (user.FactionId != 3 && user.FactionId != 1) // Zivi / Gangmember erntet ab + { + player.SyncAnimation("harvestPlant"); + plant.Harvested = true; bool isPlantRotten = DateTime.Now - plant.PlantDate > MAX_PLANT_TIME; if (isPlantRotten) { @@ -305,7 +407,7 @@ namespace ReallifeGamemode.Server.Managers if (!isPlantReadyToHarvest) // Wenn die Pflanze noch nicht ausgewachsen ist { bool getSeedBack = _random.Next(0, 2) == 1; // 50% Chance - if(getSeedBack) + if (getSeedBack) { IItem cannabisSeedItem = InventoryManager.GetItem(); InventoryManager.AddItemToInventory(player, cannabisSeedItem.Id, 1); @@ -340,15 +442,32 @@ namespace ReallifeGamemode.Server.Managers } } } - else // FIB erntet ab + else // FIB / LSPD erntet ab { + if (!(player.HasData("IsCarryingPlant") || player.GetData("IsCarryingPlant"))) + { + player.SetData("IsCarryingPlant", true); + player.SendNotification($"Du hast eine Pflanze von ~y~{plant.PlantedBy.Name}~s~ ausgegraben"); + + player.SyncAnimation("harvestPlant"); + plant.Harvested = true; + + var modelToGet = await player.TriggerProcedure("SERVER:Hanf_GetModelToGivePlayer", plant.Id); + player.SetData("HoldingCannabisPlant", modelToGet); + player.AddAttachment("CannabisPlantInHand" + modelToGet, false); + } } dbContext.SaveChanges(); UpdateHanfWorldData(dbContext); } + internal static bool IsPlayerNearCannabisSellPoint(Player player) + { + return _cannabisSellPoints.Any(p => p.DistanceTo(player.Position) <= 3); + } + internal static void BuildJointsFromCannabis(Player player) { if (player.HasAnimation(_manufacturerAnim) || _manufacturerCurrentlyUsed) @@ -396,5 +515,105 @@ namespace ReallifeGamemode.Server.Managers _manufacturerDoneTimer.Stop(); _manufacturerCurrentlyUsed = false; } + + [RemoteEvent("CLIENT:Hanf_FinishDiggingAnimation")] + public void HanfManagerFinishDiggingAnimation(Player player) + { + player.AddAttachment("shovel", true); + } + + private static int GetAmountOfCannabisSeedsPlayerCanBuyToday(User user) + { + if (user.LastTimeBoughtCannabisSeeds == null) + { + return MAX_SEEDS_PER_DAY; + } + + if (user.LastTimeBoughtCannabisSeeds.Value.Date != DateTime.Now.Date) + { + return MAX_SEEDS_PER_DAY; + } + + return MAX_SEEDS_PER_DAY - user.CannabisSeedsBoughtToday; + } + + internal static void ShowPlayerBuySeedMenu(Player player) + { + var user = player.GetUser(); + + if (user.Faction?.StateOwned == true) + { + return; + } + + var seedsUserCanBuy = GetAmountOfCannabisSeedsPlayerCanBuyToday(user); + + if (seedsUserCanBuy == 0) + { + player.SendNotification("~r~Du kannst heute keine Samen mehr kaufen"); + return; + } + + player.TriggerEvent("SERVER:Hanf_BuySeed", seedsUserCanBuy, SEED_PRICE); + } + + internal static void PlayerSellCannabis(Player player) + { + if (!player.IsLoggedIn()) + { + return; + } + using var dbContext = new DatabaseContext(); + var user = player.GetUser(dbContext); + + if (user.Faction?.StateOwned == true) + { + return; + } + + List items = InventoryManager.GetUserItems(player, dbContext); + + IItem cannabisItem = InventoryManager.GetItem(); + var cannabisAmount = items.Where(i => i.ItemId == cannabisItem.Id).FirstOrDefault()?.Amount ?? 0; + + if (cannabisAmount == 0) + { + player.SendNotification("~r~Du hast kein Cannabis dabei"); + return; + } + + player.TriggerEvent("SERVER:Hanf_SellCannabisMenu", cannabisAmount, CANNABIS_PRICE); + } + + [RemoteEvent("CLIENT:Hanf_SellCannabis")] + public void HanfManagerSellCannabis(Player player, int amount) + { + if (!player.IsLoggedIn()) + { + return; + } + + using var dbContext = new DatabaseContext(); + var user = player.GetUser(dbContext); + List items = InventoryManager.GetUserItems(player, dbContext); + + IItem cannabisItem = InventoryManager.GetItem(); + var cannabisUserItem = items.Where(i => i.ItemId == cannabisItem.Id).FirstOrDefault(); + var cannabisAmount = cannabisUserItem?.Amount ?? 0; + + if (cannabisAmount < amount) + { + player.SendNotification("~r~Du hast nicht so viel Cannabis dabei"); + return; + } + + var price = amount * CANNABIS_PRICE; + user.Handmoney += price; + InventoryManager.RemoveUserItem(user, cannabisUserItem, amount); + + logger.LogInformation("Player {0} sold {1} cannabis to the server for {2} dollars", player.Name, amount, price); + + player.SendNotification($"Du hast ~g~{amount} Hanfblüten~s~ für ~g~{price.ToMoneyString()}~s~ verkauft"); + } } } diff --git a/ReallifeGamemode.Server/Managers/InteractionManager.cs b/ReallifeGamemode.Server/Managers/InteractionManager.cs index d6d6e0ed..c769b235 100644 --- a/ReallifeGamemode.Server/Managers/InteractionManager.cs +++ b/ReallifeGamemode.Server/Managers/InteractionManager.cs @@ -18,6 +18,7 @@ using ReallifeGamemode.Server.Core.API; using ReallifeGamemode.Server.Factions.Medic; using Microsoft.Extensions.Logging; using ReallifeGamemode.Server.Log; +using ReallifeGamemode.Server.Inventory.Interfaces; /** * @overview Life of German Reallife - Managers Interaction (InteractionManager.cs) @@ -758,6 +759,150 @@ namespace ReallifeGamemode.Server.Managers } } + [RemoteEvent("CLIENT:InteractionMenu_LSPD_FriskUser")] + public void InteractionMenuLspdFriskUser(Player player, string name) + { + if (!player.IsLoggedIn()) + { + return; + } + + Player target = PlayerService.GetPlayerByNameOrId(name); + if (!target.IsLoggedIn()) + { + ChatService.PlayerNotFound(player); + return; + } + + using var dbContext = new DatabaseContext(); + var user = player.GetUser(dbContext); + + if ((user.FactionId != 1 && user.FactionId != 3) || !player.IsDuty()) + { + return; + } + + if (player.Position.DistanceTo(target.Position) > 5) + { + player.SendNotification("~r~Der Spieler ist nicht in deiner Nähe"); + return; + } + + var targetUser = target.GetUser(dbContext); + + var targetItems = InventoryManager.GetUserItems(target, dbContext); + List illItemsList = new List(); + bool illegalItemsFound = false; + var price = 0; + + foreach (var targetItem in targetItems) + { + IItem item = InventoryManager.GetItemById(targetItem.ItemId); + if (!item.Legal) + { + illItemsList.Add($"{targetItem.Amount}x {item.Name}"); + InventoryManager.RemoveUserItem(targetUser, targetItem, targetItem.Amount); + illegalItemsFound = true; + price += ((IIllegalItem)item).PriceForConfiscation * targetItem.Amount; + logger.LogInformation("Player {0} confiscated the illegal item {1} ({2}, amount: {3}) from player {4}", player.Name, item.Name, item.Id, targetItem.Amount, target.Name); + } + } + + if (!illegalItemsFound) + { + player.SendNotification("~g~Der Spieler hat keine illegalen Gegenstände dabei"); + return; + } + + logger.LogInformation("executive factions got {0} dollars from the confiscation", price); + var factions = dbContext.Factions.Include(f => f.BankAccount).Where(f => f.Id == 1 || f.Id == 3); + foreach (var faction in factions) + { + faction.BankAccount.Balance += price; + } + + dbContext.SaveChanges(); + + string illItemsStr = "~y~" + string.Join("~s~,~y~ ", illItemsList) + "~s~"; + ChatService.SendMessage(player, $"Du hast ~y~{target.Name}~s~ folgende Gegenstände abgenommen: {illItemsStr}"); + ChatService.SendMessage(target, $"~y~{player.Name}~s~ hat die folgende Gegenstände abgenommen: {illItemsStr}"); + + } + + [RemoteEvent("CLIENT:InteractionMenu_LSPD_FriskVehicle")] + public void InteractionMenuLspdFriskVehicle(Player player) + { + if (!player.IsLoggedIn()) + { + return; + } + + using var dbContext = new DatabaseContext(); + var user = player.GetUser(dbContext); + + if ((user.FactionId != 1 && user.FactionId != 3) || !player.IsDuty()) + { + return; + } + + var vehicle = NAPI.Pools.GetAllVehicles().Where(v => v.Position.DistanceTo(player.Position) <= 5).OrderBy(v => v.Position.DistanceTo(player.Position)).FirstOrDefault(); + if (vehicle == null) + { + player.SendNotification("~r~Es befindet sich kein Fahrzeug in deiner Nähe"); + return; + } + + ServerVehicle serverVehicle = vehicle.GetServerVehicle(dbContext); + if (serverVehicle == null) + { + player.SendNotification("~r~Dieses Fahrzeug kann nicht durchsucht werden"); + return; + } + + if (VehicleStreaming.GetLockState(vehicle) || serverVehicle.Locked) + { + player.SendNotification("~r~Dieses Fahrzeug ist abgeschlossen"); + return; + } + + var targetItems = InventoryManager.GetVehicleItems(vehicle); + List illItemsList = new List(); + bool illegalItemsFound = false; + var price = 0; + + foreach (var targetItem in targetItems) + { + IItem item = InventoryManager.GetItemById(targetItem.ItemId); + if (!item.Legal) + { + illItemsList.Add($"{targetItem.Amount}x {item.Name}"); + InventoryManager.RemoveVehicleItem(serverVehicle, targetItem, targetItem.Amount, null); + illegalItemsFound = true; + price += ((IIllegalItem)item).PriceForConfiscation * targetItem.Amount; + logger.LogInformation("Player {0} confiscated the illegal item {1} ({2}, amount: {3}) from vehicle {4}", player.Name, item.Name, item.Id, targetItem.Amount, serverVehicle.Id); + } + } + + if (!illegalItemsFound) + { + player.SendNotification("~g~Im Kofferraum sind keine illegalen Gegenstände"); + return; + } + + logger.LogInformation("executive factions got {0} dollars from the confiscation", price); + + var factions = dbContext.Factions.Include(f => f.BankAccount).Where(f => f.Id == 1 || f.Id == 3); + foreach (var faction in factions) + { + faction.BankAccount.Balance += price; + } + + dbContext.SaveChanges(); + + string illItemsStr = "~y~" + string.Join("~s~,~y~ ", illItemsList) + "~s~"; + ChatService.SendInRange(player.Position, 20, $"{player.Name} hat aus dem Kofferraum folgende Gegenstände beschlagnahmt: {illItemsStr}"); + } + [RemoteEvent("CLIENT:InteractionMenu_Pay")] public void InteractionMenu_Pay(Player player, string jsonNameOrId, string stringAmount) { diff --git a/ReallifeGamemode.Server/Managers/InventoryManager.cs b/ReallifeGamemode.Server/Managers/InventoryManager.cs index aaa1b434..e8cfea56 100644 --- a/ReallifeGamemode.Server/Managers/InventoryManager.cs +++ b/ReallifeGamemode.Server/Managers/InventoryManager.cs @@ -47,7 +47,7 @@ namespace ReallifeGamemode.Server.Managers public int Amount; public int ItemId; public int Weight; - public Vehicle vehicle; + public ushort vehicle; } public static void SetBackpackItems(Player player) @@ -75,9 +75,9 @@ namespace ReallifeGamemode.Server.Managers player.SetSharedData("backpackItems", JsonConvert.SerializeObject(backpackItems[player].ToArray())); } - internal static IItem GetItem() where T : IItem + internal static T GetItem() where T : IItem { - return itemList.Where(i => i.GetType() == typeof(T)).First(); + return (T)itemList.Where(i => i.GetType() == typeof(T)).First(); } [RemoteEvent("CLIENT:getVehicleInventory")] @@ -86,7 +86,9 @@ namespace ReallifeGamemode.Server.Managers if (player.IsInVehicle) { player.TriggerEvent("Error", "Du kannst deinen Kofferraum gerade nicht öffnen."); + return; } + Vehicle veh = NAPI.Pools.GetAllVehicles() .ToList() .Where(v => v.Position.DistanceTo(player.Position) <= 4) @@ -131,7 +133,7 @@ namespace ReallifeGamemode.Server.Managers Amount = i.Amount, ItemId = i.ItemId, Weight = GetVehicleInventoryWeight(veh), - vehicle = veh, + vehicle = veh.Handle.Value, }; vehicleItems[player].Add(newItem); } @@ -197,6 +199,10 @@ namespace ReallifeGamemode.Server.Managers public static void RemoveVehicleItem(ServerVehicle sVeh, VehicleItem item, int amount, Player player) { + if (item == null) + { + return; + } using (var dbContext = new DatabaseContext()) { var vehicleItem = dbContext.VehicleItems.FirstOrDefault(i => i.Id == item.Id); @@ -327,20 +333,29 @@ namespace ReallifeGamemode.Server.Managers using (var context = new DatabaseContext()) { + User user = player.GetUser(context); if (!vehicleItems.ContainsKey(player)) vehicleItems.Add(player, new List()); Vehicle veh = null; if (vehicleItems[player].Count != 0) - veh = vehicleItems[player].FirstOrDefault().vehicle; + veh = new NetHandle(vehicleItems[player].FirstOrDefault().vehicle, EntityType.Vehicle).Entity(); ServerVehicle serverVehicle = VehicleManager.GetServerVehicleFromVehicle(veh, context); - VehicleItem vehItem = context.VehicleItems.Where(v => v.VehicleId == serverVehicle.Id && v.ItemId == itemID).FirstOrDefault(); if (vehItem == null) { player.TriggerEvent("Error", "Transfer nicht möglich."); return; } + if (serverVehicle is FactionVehicle factionVehicle) + { + IItem item = GetItemById(itemID); + if (factionVehicle.Model == VehicleHash.Riot && user.Faction?.StateOwned == true) + { + player.TriggerEvent("Error", "Transfer nicht möglich."); + return; + } + } RemoveVehicleItem(serverVehicle, vehItem, itemAmount, player); SetVehicleItems(player);