Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v3.3 Alpha #1038

Merged
merged 87 commits into from
Dec 2, 2024
Merged
Show file tree
Hide file tree
Changes from 79 commits
Commits
Show all changes
87 commits
Select commit Hold shift + click to select a range
a57cda2
fix zombies on NG+ in halloween modes
Die4Ever Oct 31, 2024
43ab58c
make paris chill discription more clear (#1025)
MQDuck Oct 31, 2024
2054467
immediately mark OverhearLebedev_Played as failed when you talk to le…
MQDuck Oct 31, 2024
c14c16f
make it impossible to get around the airfield elevator teleporter (#1…
MQDuck Oct 31, 2024
a8b8ea1
Fix Sign up for the Knicks bingo goal and Rescue the bum on the
theastropath Nov 1, 2024
a80131d
bump version to v3.2.5.0 Alpha for dev purposes
Die4Ever Nov 2, 2024
95b47be
The inventory description for Aug Canisters now show the aug location
theastropath Nov 5, 2024
069e96b
New option to randomize the slot augs occupy.
theastropath Nov 7, 2024
426717a
horde mode always have merchant
Die4Ever Nov 7, 2024
06c9f64
fix mishandled end credits values
Die4Ever Nov 7, 2024
0c22932
Aug Slot Rando now accepts a percentage from 0 to 100, chance for each
theastropath Nov 7, 2024
3d5142c
Hacking window on computers now has a Use Biocell button
theastropath Nov 8, 2024
dab3c19
Hacking screen biocell count actually goes to 0
theastropath Nov 8, 2024
a7b9b11
Improve Swirl and Health colour schemes so that some text is more
theastropath Nov 9, 2024
0175c31
Add missing breaks
theastropath Nov 9, 2024
4fbd3b4
Fix Walton Simons not having proper collision when he spawns at sub base
theastropath Nov 9, 2024
d16d617
Add option to Legend Show Class to show collision values
theastropath Nov 9, 2024
1f75d2d
Coolant Alarm moves with Generator Computer in mission 2. Alarm also
theastropath Nov 10, 2024
17ee7f2
fix some things dependant on injection order
Die4Ever Nov 10, 2024
8b22a36
actually fix some things dependant on injection order
Die4Ever Nov 10, 2024
a4261a5
Bring Revision mission goals in line with Vanilla for Mission 1 and 2
theastropath Nov 10, 2024
fc06f47
Align Revision mission 4/6/8 goals with Vanilla
theastropath Nov 10, 2024
9fadaa3
Align Revision mission goals with Vanilla from mission 9 onwards
theastropath Nov 10, 2024
f2c963f
Add ShuffleGoals, CheatsOn, CheatsOff cheats to DXRandoGameInfo for
theastropath Nov 11, 2024
0cc2b10
More endgame quotes (#1029)
MQDuck Nov 11, 2024
a9cbd89
Add Advanced New Game setting for zombies. Add zombie chance to NG+ (…
MQDuck Nov 11, 2024
c332297
Make Halloween modes less prominent in game mode selection screen (#1…
MQDuck Nov 11, 2024
4b20c7a
zombie time based on difficulty
Die4Ever Nov 11, 2024
63c5df2
New Revision-Only goal locations and other minor Revision adjustments.
theastropath Nov 12, 2024
93601fb
DXRReplaceActors now also replaces actors cached in DXRMissions
theastropath Nov 12, 2024
102afec
Increase actor_watch array size. DXRReplaceActors updates references in
theastropath Nov 12, 2024
62c039e
Fix PlaceholderItems that were OutOfWorld in Revision
theastropath Nov 12, 2024
a41e97a
Datacube shuffling works in Revision again, and port Datacube Rules.
theastropath Nov 13, 2024
bae19de
Fix Revision placeholders in UNATCO HQ and Hotel.
theastropath Nov 13, 2024
b67a881
Update Area 51 Blast Doors bingo description
theastropath Nov 13, 2024
d15f940
All spawned datacubes now have defined spawn coordinates #994
theastropath Nov 14, 2024
16a6705
Crowd Control will now spawn DXRPiano's in Revision etc, instead of
theastropath Nov 15, 2024
a6ba0b2
Spawned datacubes can now be assigned a string texttag for better
theastropath Nov 16, 2024
a3c000c
Update fixed add_datacube locations to make sure they all work for
theastropath Nov 16, 2024
b5b5080
Define spawn locations for extra items in 02_NYC_WAREHOUSE ( #994 )
theastropath Nov 17, 2024
220058d
Port ALL placeholders to Revision (Containers, Enemies, Items)
theastropath Nov 18, 2024
72fd131
Fix Vandenberg Tunnels getting skipped on first entry in non-Vanilla
theastropath Nov 18, 2024
fe1ba2d
Quick Aug and Quick Skill menus start every load closed (even if it was
theastropath Nov 18, 2024
b5d79df
Revision UNATCO HQ turrets are now non-hostile (prevents them from being
theastropath Nov 18, 2024
b2a7df4
DXRFashionManager forcibly disables HDTP JC and Paul in Revision #1030
theastropath Nov 18, 2024
c05af16
Improve key rules for neo-carcharod lab and Oceanguard datacube in
theastropath Nov 19, 2024
b01df4c
Only UNATCO troops get shuffled in NSF HQ (to prevent civilians from
theastropath Nov 24, 2024
cade25b
Datacube Rules can now use a text package, and added rules for M05 MJ12
theastropath Nov 24, 2024
0aedd85
Fix key rule for lebedev 747 private quarters door key to exclude
theastropath Nov 24, 2024
47f08fe
Improve datacube rules for Revision armoury door code and key rules for
theastropath Nov 26, 2024
dcea4a4
Prevent items in sealed windows in Revision Cathedral from being
theastropath Nov 26, 2024
34d0a16
Make sure turret in Revision Everett is non-hostile
theastropath Nov 26, 2024
fdca3ba
Add music randomization for Revision (and PS2) OGG soundtrack
theastropath Nov 27, 2024
574b84d
Remove duplicate OGG songs for Revision, remove debugging clientmessage
theastropath Nov 27, 2024
40641c4
Augbots don't get facelifted in Revision
theastropath Nov 28, 2024
4a81a43
GlowUp check for datacubes is more generic to work with Revision.
theastropath Nov 28, 2024
c41b7ca
DynamicLights get moved to the new InformationDevice when replaced in
theastropath Nov 28, 2024
cd9902b
Ogg Music gets randomized on AnyEntry so that info is populated
theastropath Nov 28, 2024
0459180
Don't copy mover settings between default named BreakableGlass and
theastropath Nov 28, 2024
e502968
More generic solution for copying mover settings across sets of doors
theastropath Nov 28, 2024
699efb7
Music Randomization no longer modifies the DXOggMusicInfo in the level,
theastropath Nov 29, 2024
bbe3426
Random Music menu button will now actually switch between randomized and
theastropath Nov 29, 2024
0c26938
Revision NSF HQ, Walton infolink plays and UNATCO goes hostile
theastropath Nov 29, 2024
62ac567
Requesting fearless Alex and Jaime in Revision M05
theastropath Nov 29, 2024
bb91770
Ocean Lab UC "schematic downloaded" infolink plays immediately in
theastropath Nov 30, 2024
b1fa28d
Le Merchant actually spawns in the right map in Revision
theastropath Nov 30, 2024
f0a3563
Revision Lucky Money Interior song starts immediately instead of play…
theastropath Nov 30, 2024
5570e9a
Port several Area 51 Bunker fixes from Vanilla to Revision
theastropath Nov 30, 2024
0871044
Add M02 Battery Park boat exit MapExit for Revision maps
theastropath Nov 30, 2024
a5f3926
Medbot/Repairbot hint datacubes are actually placed in a radius around
theastropath Nov 30, 2024
45d931b
Revision Area 51 vent entrance is now harder, like in vanilla (Top door
theastropath Nov 30, 2024
41797c8
Maggie's Display Case in Revision no longer gets triggered when the
theastropath Nov 30, 2024
aba85f6
Some hint changes (#1028)
MQDuck Nov 30, 2024
d762756
fix HX build
Die4Ever Nov 30, 2024
9db984c
Revision blocks facelift on the Earth globe if memes are enabled, so
theastropath Nov 30, 2024
a72f059
Switches on upper decks of superfreighter to open locked doors ported
theastropath Dec 1, 2024
d017c64
Brought various VanillaMaps fixes over to Revision:
theastropath Dec 1, 2024
93e8534
Remove various unnecessary lookups of the RevisionMaps state
theastropath Dec 1, 2024
2d3212c
Fix for Maggie's DispalyCase applies to all maps, not just Revision
theastropath Dec 2, 2024
76b7b6b
Locations in Paris Revision map fixups use vectm instead of vect (just
theastropath Dec 2, 2024
5abcbca
Mission 15 goal rando for PAGE returns 154 instead of 152 (to leave
theastropath Dec 2, 2024
8d06494
Menu Choice button for Revision Music now subclasses from other music
theastropath Dec 2, 2024
f361960
one item mode for stable builds, cleanup in BalanceHacking.uc
Die4Ever Dec 2, 2024
c9c8be8
Add Sax versions of Intro and Paris themes to Revision Music rando
theastropath Dec 2, 2024
79ed3e6
Ogg Music Rando uses the ambient track as the outro if the outro track
theastropath Dec 2, 2024
2835775
Mr. Page's Mean Bingo Machine (#1036)
MQDuck Dec 2, 2024
dfdc3fb
v3.3.0.0 Alpha builds
Die4Ever Dec 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 0 additions & 15 deletions DXRBalance/DeusEx/Classes/AugmentationManager.uc
Original file line number Diff line number Diff line change
Expand Up @@ -69,21 +69,6 @@ function Augmentation GetAugByKey(int keyNum)
return None;
}

simulated function Augmentation GetAug(class<Augmentation> AugClass)
{
local Augmentation anAug;

anAug = FirstAug;
while(anAug != None)
{
if (anAug.Class == augClass)
return anAug;
anAug = anAug.next;
}

return None;
}

// ----------------------------------------------------------------------
// GetAugLevelValue()
//
Expand Down
120 changes: 118 additions & 2 deletions DXRBalance/DeusEx/Classes/BalanceHacking.uc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ var TextWindow energyMeter;
var Color colWhite;
var int energyMeterTimer;

var PersonaActionButtonWindow btnBiocell;
var String BiocellButtonLabel;
var int biocellCount;


function Tick(float deltaTime)
{
local Human p;
Expand Down Expand Up @@ -63,9 +68,116 @@ function CreateHackMessageWindow()
energyMeterTimer = AddTimer(0.1, true, 0, 'UpdateEnergyMeterTimer');
}

function CreateHackButton()
{
local #var(PlayerPawn) p;

//Make the hacking button
Super.CreateHackButton();

p = #var(PlayerPawn)(player);
if (p==None || p.bZeroRando) return;

//Make the Biocell button as well
btnBiocell = PersonaActionButtonWindow(NewChild(Class'DXRPersonaActionButtonWindow'));
btnBioCell.minimumButtonWidth=111;
btnBioCell.SetPos(83,86);
btnBioCell.CenterText(true);
UpdateBiocellButtonCount();
}

function UpdateBiocellButtonCount()
{
local #var(prefix)BioElectricCell bc;
local #var(PlayerPawn) p;

p = #var(PlayerPawn)(player);

if (p==None || btnBiocell==None || p.bZeroRando) return;

biocellCount = 0;
if (p!=None){
bc = #var(prefix)BioElectricCell(p.FindInventoryType(class'#var(prefix)BioElectricCell'));
if (bc!=None){
biocellCount = bc.NumCopies;
}
}

btnBiocell.SetButtonText(BiocellButtonLabel$" ("$biocellCount$")");

UpdateBiocellButtonClickability();

}

function UpdateBiocellButtonClickability()
{
local bool enable;
local #var(PlayerPawn) p;

p = #var(PlayerPawn)(player);
enable=False;

if (p==None || btnBiocell==None || p.bZeroRando) return;

if (p!=None && biocellCount!=0){
if (p.Energy<p.EnergyMax){
enable=True;
}
}

if (!bHacked){
btnBiocell.EnableWindow(enable);
} else {
btnBiocell.Hide(); //Hide biocell button once the computer is hacked
}
}

function HandleBiocellButton()
{
local #var(prefix)BioElectricCell bc;
local #var(PlayerPawn) p;

p = #var(PlayerPawn)(player);

if (p!=None){
bc = #var(prefix)BioElectricCell(p.FindInventoryType(class'#var(prefix)BioElectricCell'));
if (bc!=None){
bc.Activate();
UpdateBiocellButtonCount();
}
}
}

function bool ButtonActivated( Window buttonPressed )
{
local bool bHandled;
local #var(PlayerPawn) p;

p = #var(PlayerPawn)(player);

bHandled = False;

if (p==None || btnBiocell==None || p.bZeroRando) return Super.ButtonActivated(buttonPressed);

switch( buttonPressed )
{
case btnBiocell:
bHandled=True;
HandleBiocellButton();
break;
}

if (bHandled){
return True;
} else {
return Super.ButtonActivated(buttonPressed);
}
}

function UpdateEnergyMeterTimer(int timerID, int invocations, int clientData)
{
UpdateEnergyMeter();
UpdateBiocellButtonClickability(); //Button can change clickability based on remaining energy
}

event DestroyWindow()
Expand All @@ -82,7 +194,7 @@ event DestroyWindow()
function UpdateEnergyMeter()
{
local Human p;
local int energy,energydec,req,reqdec;
local int energy,energydec,req,reqdec,maxenergy,maxenergydec;
local float reqEnergy;
local string msg;

Expand All @@ -94,12 +206,15 @@ function UpdateEnergyMeter()
energy = int(p.Energy);
energydec = int((p.Energy * 10) - (energy*10));

maxenergy = int(p.EnergyMax);
maxenergydec = int((p.EnergyMax * 10) - (maxenergy*10));

reqEnergy = hackTime * 5.0;
req = int(reqEnergy);
reqdec = int((reqEnergy*10) - (req*10));


msg = "Energy: "$energy$"."$energydec;
msg = "Energy: "$energy$"."$energydec$" / "$maxenergy$"."$maxenergydec;

if (!bHacking) {
msg = msg$"|n";
Expand Down Expand Up @@ -139,4 +254,5 @@ defaultproperties
{
colWhite=(R=255,G=255,B=255)
energyMeterTimer=-1
BiocellButtonLabel="Use |&Biocell"
}
4 changes: 2 additions & 2 deletions DXRBalance/DeusEx/Classes/BuffTechGoggles.uc
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ function UpdateHUDDisplay(DeusExPlayer Player)
local AugmentationDisplayWindow augDisplay;
local float dist;

aug = AugVision(Player.AugmentationSystem.GetAug(class'AugVision'));
aug = AugVision(Player.AugmentationSystem.FindAugmentation(class'AugVision'));
dist = CalcDistance(aug);

augDisplay = DeusExRootWindow(Player.rootWindow).hud.augDisplay;
Expand Down Expand Up @@ -69,7 +69,7 @@ function ChargedPickupEnd(DeusExPlayer Player)
augDisplay.visionBlinder = None;
} else {
augDisplay.visionLevel -= 1;
aug = AugVision(Player.AugmentationSystem.GetAug(class'AugVision'));
aug = AugVision(Player.AugmentationSystem.FindAugmentation(class'AugVision'));
augDisplay.visionLevelValue -= CalcDistance(aug);
}

Expand Down
18 changes: 13 additions & 5 deletions DXRCore/DeusEx/Classes/DXRActorsBase.uc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ struct FMinMax {

struct safe_rule {
var name item_name;
var string package_name;
var vector min_pos;
var vector max_pos;
var bool allow;
Expand Down Expand Up @@ -1137,14 +1138,15 @@ function #var(injectsprefix)InformationDevices SpawnDatacube(vector loc, rotator
}


function #var(injectsprefix)InformationDevices SpawnDatacubePlaintext(vector loc, rotator rot, string text, optional bool dont_move)
function #var(injectsprefix)InformationDevices SpawnDatacubePlaintext(vector loc, rotator rot, string text, string plaintextTag, optional bool dont_move)
{
local #var(injectsprefix)InformationDevices dc;

dc = SpawnDatacube(loc,rot,dont_move);

if(dc != None) {
dc.plaintext = text;
dc.plaintextTag=plaintextTag;
}
return dc;
}
Expand Down Expand Up @@ -1204,7 +1206,7 @@ function Actor SpawnReplacement(Actor a, class<Actor> newclass, optional bool do

l("SpawnReplacement("$a$", "$newclass$") " $ newactor);

newactor.SetCollision(bCollideActors, bBlockActors, bBlockPlayers);
newactor.RotationRate=a.RotationRate;
newactor.SetPhysics(a.Physics);
newactor.SetBase(a.Base);
newactor.Event = event;
Expand All @@ -1231,6 +1233,10 @@ function Actor SpawnReplacement(Actor a, class<Actor> newclass, optional bool do
newactor.SetPropertyText("PrecessorName", a.GetPropertyText("PrecessorName"));
}

//SetBase resets the collision to... defaults?
//Do this last for safety
newactor.SetCollision(bCollideActors, bBlockActors, bBlockPlayers);

return newactor;
}

Expand Down Expand Up @@ -1691,12 +1697,13 @@ function safe_rule FixSafeRule(safe_rule r)
return r;
}

function int GetSafeRule(safe_rule rules[16], name item_name, vector newpos)
function int GetSafeRule(safe_rule rules[16], coerce string item_name, string package_name, vector newpos)
{
local int i;

for(i=0; i<ArrayCount(rules); i++) {
if( item_name != rules[i].item_name ) continue;
if( !(item_name ~= string(rules[i].item_name) )) continue;
if( !(package_name ~= rules[i].package_name )) continue;
if( AnyGreater( rules[i].min_pos, newpos ) ) continue;
if( AnyGreater( newpos, rules[i].max_pos ) ) continue;
return i;
Expand Down Expand Up @@ -1754,7 +1761,8 @@ function RemoveMoverPrePivot(Mover m)
static function Actor GlowUp(Actor a, optional byte hue, optional byte saturation)
{
// if `a` is a datacube, spawn a new light instead
if (#var(prefix)DataCube(a) != None) {
// Weirdly generalized check here, since non-vanilla replaces with InformationDevices
if (#var(prefix)InformationDevices(a) != None && a.Mesh == class'#var(prefix)DataCube'.default.Mesh) {
a = a.Spawn(class'DynamicLight', a,, a.Location + vect(0, 0, 6.0));
a.SetBase(a.Owner);
a.LightSaturation = 0;
Expand Down
16 changes: 11 additions & 5 deletions DXRCore/DeusEx/Classes/DXRMenuSetupRando.uc
Original file line number Diff line number Diff line change
Expand Up @@ -245,26 +245,29 @@ function BindControls(optional string action)
NewMenuItem("Enemy Weapons Variety %", "Should enemies be using weapons that normally exist in the map?");
Slider(f.moresettings.enemies_weapons, 0, 100);

NewMenuItem("Robot Weapons Rando %", "Allow robots to get randomized weapons.");
Slider(f.settings.bot_weapons, 0, 100);

NewMenuItem("Non-Human Chance %", "Reduce the chance of new enemies being non-humans.");
Slider(f.settings.enemies_nonhumans, 0, 100);

NewMenuItem("Enemy Respawn Seconds", "How many seconds for enemies to respawn. Leave blank or 0 to disable.");
Slider(f.settings.enemyrespawn, 0, 10000);
Slider(f.settings.enemyrespawn, 0, 3600);

NewMenuItem("Reanimation Seconds", "Approximately how many seconds for corpses to come back as zombies. Leave blank or 0 to disable.");
Slider(f.moresettings.reanimation, 0, 3600);

NewMenuItem("Move Turrets", "Randomizes locations of turrets, cameras, and security computers for them.");
Slider(f.settings.turrets_move, 0, 100);

NewMenuItem("Add Turrets", "Randomly adds turrets, cameras, and security computers for them.");
Slider(f.settings.turrets_add, 0, 10000);

NewMenuItem("Robot Weapons Rando %", "Allow robots to get randomized weapons.");
Slider(f.settings.bot_weapons, 0, 100);

NewMenuItem("", "Allow non-humans to get randomized stats.");
EnumOption("Unchanged Non-human Stats", 0, f.settings.bot_stats);
EnumOption("Random Non-human Stats", 100, f.settings.bot_stats);

NewMenuItem("Paris Chill %", "Removes MJ12 from the Champs-Elysees.");
NewMenuItem("Paris Chill %", "Chance to remove all MJ12 from the Champs-Elysees.");
Slider(f.remove_paris_mj12, 0, 100);


Expand Down Expand Up @@ -362,6 +365,9 @@ function BindControls(optional string action)
NewMenuItem("Aug Strength Rando %", "How much to randomize the strength of augmentations.");
Slider(f.settings.aug_value_rando, 0, 100);// this is a wet/dry scale, 0 to 100%

NewMenuItem("Aug Slot Rando %", "The chance for each aug to randomize the body part it can be installed into");
Slider(f.moresettings.aug_loc_rando, 0, 100);

NewGroup("New Game+");

NewMenuItem("Scaling %", "Scales the curve of New Game+ changes over successive loops. Set to -1 to disable. 100% is default.");
Expand Down
8 changes: 4 additions & 4 deletions DXRCore/DeusEx/Classes/DXRVersion.uc
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,21 @@ simulated static function CurrentVersion(optional out int major, optional out in
{
major=3;
minor=2;
patch=4;
build=2;//build can't be higher than 99
patch=5;
build=1;//build can't be higher than 99
}

simulated static function bool VersionIsStable()
{
return true;
return false;
}

simulated static function string VersionString(optional bool full)
{
local int major,minor,patch,build;
local string status;

status = "";
status = "Alpha";

if(status!="") {
status = " " $ status;
Expand Down
6 changes: 5 additions & 1 deletion DXRCore/DeusEx/Classes/DXRando.uc
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ function CheckConfig()
player.bAskedToTrain = false;
player.SaveConfig();
}
if( VersionOlderThan(config_version, 3,2,3,3) ) {
if( VersionOlderThan(config_version, 3,2,5,1) ) {
for(i=0; i < ArrayCount(modules_to_load); i++) {
modules_to_load[i] = "";
}
Expand Down Expand Up @@ -215,6 +215,7 @@ function vanilla_modules()
modules_to_load[i++] = "DXRHordeMode";
//modules_to_load[i++] = "DXRKillBobPage";
modules_to_load[i++] = "DXREnemyRespawn";
modules_to_load[i++] = "DXRZombies";
modules_to_load[i++] = "DXRLoadouts";
modules_to_load[i++] = "DXRWeapons";
modules_to_load[i++] = "DXRCrowdControl";
Expand Down Expand Up @@ -255,6 +256,7 @@ function hx_modules()
modules_to_load[i++] = "DXREnemies";
modules_to_load[i++] = "DXRHordeMode";
modules_to_load[i++] = "DXREnemyRespawn";
modules_to_load[i++] = "DXRZombies";
modules_to_load[i++] = "DXRLoadouts";
modules_to_load[i++] = "DXRWeapons";
modules_to_load[i++] = "DXRCrowdControl";
Expand Down Expand Up @@ -290,6 +292,7 @@ function gmdx_modules()
modules_to_load[i++] = "DXREnemies";
modules_to_load[i++] = "DXRHordeMode";
modules_to_load[i++] = "DXREnemyRespawn";
modules_to_load[i++] = "DXRZombies";
modules_to_load[i++] = "DXRLoadouts";
modules_to_load[i++] = "DXRWeapons";
modules_to_load[i++] = "DXRCrowdControl";
Expand Down Expand Up @@ -335,6 +338,7 @@ function vmd_modules()
modules_to_load[i++] = "DXREnemies";
modules_to_load[i++] = "DXRHordeMode";
modules_to_load[i++] = "DXREnemyRespawn";
modules_to_load[i++] = "DXRZombies";
modules_to_load[i++] = "DXRLoadouts";
modules_to_load[i++] = "DXRWeapons";
modules_to_load[i++] = "DXRCrowdControl";
Expand Down
Loading