first version

This commit is contained in:
GenZmeY 2021-02-20 13:30:45 +03:00
parent a303dec4de
commit cb6a0e28c3
13 changed files with 574 additions and 1 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
testing.ini
3rd-party-bin

View File

@ -0,0 +1,8 @@
class MskGsGFxMenu_Trader extends KFGFxMenu_Trader
dependsOn(MskGsGFxTraderContainer_Store);
defaultproperties
{
SubWidgetBindings.Remove((WidgetName="shopContainer",WidgetClass=class'KFGFxTraderContainer_Store'))
SubWidgetBindings.Add((WidgetName="shopContainer",WidgetClass=class'MskGsGFxTraderContainer_Store'))
}

View File

@ -0,0 +1,8 @@
class MskGsGFxMoviePlayer_Manager extends KFGFxMoviePlayer_Manager
dependsOn(MskGsGFxMenu_Trader);
defaultproperties
{
WidgetBindings.Remove((WidgetName="traderMenu",WidgetClass=class'KFGFxMenu_Trader'))
WidgetBindings.Add((WidgetName="traderMenu",WidgetClass=class'MskGsGFxMenu_Trader'))
}

View File

@ -0,0 +1,35 @@
class MskGsGFxTraderContainer_Store extends KFGFxTraderContainer_Store;
var bool GroupMember;
function Initialize(KFGFxObject_Menu NewParentMenu)
{
local OnlineSubsystemSteamworks OnlineSub;
local UniqueNetId GroupID;
super.Initialize(NewParentMenu);
OnlineSub = OnlineSubsystemSteamworks(class'GameEngine'.static.GetOnlineSubsystem());
class'OnlineSubsystem'.Static.StringToUniqueNetId("0x017000000223386E", GroupID);
GroupMember = OnlineSub.CheckPlayerGroup(GroupID);
}
function bool IsItemFiltered(STraderItem Item, optional bool bDebug)
{
if (KFPC.GetPurchaseHelper().IsInOwnedItemList(Item.ClassName))
return true;
if (KFPC.GetPurchaseHelper().IsInOwnedItemList(Item.DualClassName))
return true;
if (!KFPC.GetPurchaseHelper().IsSellable(Item))
return true;
if (!GroupMember && Item.WeaponDef.default.SharedUnlockId != SCU_None && !class'KFUnlockManager'.static.IsSharedContentUnlocked(Item.WeaponDef.default.SharedUnlockId))
return true;
if (Item.WeaponDef.default.PlatformRestriction != PR_All && class'KFUnlockManager'.static.IsPlatformRestricted(Item.WeaponDef.default.PlatformRestriction))
return true;
return false;
}
defaultproperties
{
}

46
MskGs/Classes/MskGsMut.uc Normal file
View File

@ -0,0 +1,46 @@
Class MskGsMut extends KFMutator;
simulated event PostBeginPlay()
{
super.PostBeginPlay();
if (WorldInfo.Game.BaseMutator == None)
WorldInfo.Game.BaseMutator = Self;
else
WorldInfo.Game.BaseMutator.AddMutator(Self);
if (bDeleteMe)
return;
Initialize();
}
function Initialize()
{
if (MyKFGI == None || MyKFGI.MyKFGRI == None)
{
SetTimer(2.f, false, nameof(Initialize));
return;
}
MyKFGI.KFGFxManagerClass = class'MskGsGFxMoviePlayer_Manager';
MyKFGI.MyKFGRI.VoteCollectorClass = class'MskGsVoteCollector';
MyKFGI.MyKFGRI.PostBeginPlay();
`Log("[MskGsMut] Mutator loaded.");
}
function AddMutator(Mutator Mut)
{
if (Mut == Self)
return;
if (Mut.Class == Class)
Mut.Destroy();
else
Super.AddMutator(Mut);
}
defaultproperties
{
}

View File

@ -0,0 +1,4 @@
[Flags]
AllowDownload=True
ClientOptional=False
ServerSideOnly=False

View File

@ -0,0 +1,241 @@
class MskGsVoteCollector extends KFVoteCollector;
var private const array<string> ImportantPersonList;
var private array<KFPlayerController> PunishList;
function ServerStartPunishment()
{
local KFGameReplicationInfo KFGRI;
local KFGameInfo KFGI;
local KFPlayerController KFPC;
local int i;
if (PunishList.Length == 0)
return;
KFGRI = KFGameReplicationInfo(WorldInfo.GRI);
KFGI = KFGameInfo(WorldInfo.Game);
for (i=0; i < PunishList.Length; i++)
{
KFPC = PunishList[i];
if (KFGRI.bMatchHasBegun)
{
KFPC.Suicide();
}
else if (KFGI.AccessControl != none)
{
KFAccessControl(KFGI.AccessControl).ForceKickPlayer(KFPC, KFGI.AccessControl.KickedMsg);
KFGI.BroadcastLocalized(KFGI, class'KFLocalMessage', LMT_KickVoteSucceeded, CurrentKickVote.PlayerPRI);
}
}
PunishList.Length = 0;
}
function bool ImportantKickee(PlayerReplicationInfo PRI_Kickee, PlayerReplicationInfo PRI_Kicker)
{
local string PunishMessage;
local KFPlayerController KFPC_Kicker;
if (ImportantPersonList.Find(class'OnlineSubsystem'.Static.UniqueNetIdToString(PRI_Kickee.UniqueId)) != -1)
{
KFPC_Kicker = KFPlayerController(PRI_Kicker.Owner);
if (PunishList.Find(KFPC_Kicker) == -1)
{
PunishMessage = PRI_Kicker.PlayerName@"tried to kick"@PRI_Kickee.PlayerName@", but sat down on the bottle instead (^_^)";
WorldInfo.Game.Broadcast(KFPC_Kicker, PunishMessage);
PunishList.AddItem(KFPC_Kicker);
SetTimer(2.0f, false, 'ServerStartPunishment', self);
}
return true;
}
return false;
}
function ServerStartVoteKick(PlayerReplicationInfo PRI_Kickee, PlayerReplicationInfo PRI_Kicker)
{
local int i;
local array<KFPlayerReplicationInfo> PRIs;
local KFGameInfo KFGI;
local KFPlayerController KFPC, KickeePC;
KFGI = KFGameInfo(WorldInfo.Game);
KFPC = KFPlayerController(PRI_Kicker.Owner);
KickeePC = KFPlayerController(PRI_Kickee.Owner);
// Kick voting is disabled
if(KFGI.bDisableKickVote)
{
KFPC.ReceiveLocalizedMessage(class'KFLocalMessage', LMT_KickVoteDisabled);
return;
}
// Spectators aren't allowed to vote
if(PRI_Kicker.bOnlySpectator)
{
KFPC.ReceiveLocalizedMessage(class'KFLocalMessage', LMT_KickVoteNoSpectators);
return;
}
// Not enough players to start a vote
if( KFGI.NumPlayers <= 2 )
{
KFPC.ReceiveLocalizedMessage(class'KFLocalMessage', LMT_KickVoteNotEnoughPlayers);
return;
}
// Maximum number of players kicked per match has been reached
if( KickedPlayers >= 2 )
{
KFPC.ReceiveLocalizedMessage(class'KFLocalMessage', LMT_KickVoteMaxKicksReached);
return;
}
// Bottling
if (ImportantKickee(PRI_Kickee, PRI_Kicker))
{
return;
}
// Can't kick admins
if(KFGI.AccessControl != none)
{
if(KFGI.AccessControl.IsAdmin(KickeePC))
{
KFPC.ReceiveLocalizedMessage(class'KFLocalMessage', LMT_KickVoteAdmin);
return;
}
}
// Last vote failed, must wait until failed vote cooldown before starting a new vote
if( bIsFailedVoteTimerActive )
{
KFPC.ReceiveLocalizedMessage(class'KFLocalMessage', LMT_KickVoteRejected);
return;
}
// A kick vote is not allowed while another vote is active
if(bIsSkipTraderVoteInProgress)
{
KFPC.ReceiveLocalizedMessage(class'KFLocalMessage', LMT_OtherVoteInProgress);
return;
}
if( !bIsKickVoteInProgress )
{
// Clear voter array
PlayersThatHaveVoted.Length = 0;
// Cache off these values in case player leaves before vote ends -- no cheating!
CurrentKickVote.PlayerID = PRI_Kickee.UniqueId;
CurrentKickVote.PlayerPRI = PRI_Kickee;
CurrentKickVote.PlayerIPAddress = KickeePC.GetPlayerNetworkAddress();
bIsKickVoteInProgress = true;
GetKFPRIArray(PRIs);
for (i = 0; i < PRIs.Length; i++)
{
PRIs[i].ShowKickVote(PRI_Kickee, VoteTime, !(PRIs[i] == PRI_Kicker || PRIs[i] == PRI_Kickee));
}
KFGI.BroadcastLocalized(KFGI, class'KFLocalMessage', LMT_KickVoteStarted, CurrentKickVote.PlayerPRI);
WorldInfo.Game.Broadcast(KFPC, PRI_Kicker.PlayerName@"starts voting for kick"@PRI_Kickee.PlayerName);
SetTimer( VoteTime, false, nameof(ConcludeVoteKick), self );
// Cast initial vote
RecieveVoteKick(PRI_Kicker, true);
}
else if(PRI_Kickee == CurrentKickVote.PlayerPRI)
{
RecieveVoteKick(PRI_Kicker, false);
}
else
{
// Can't start a new vote until current one is over
KFPlayerController(PRI_Kicker.Owner).ReceiveLocalizedMessage(class'KFLocalMessage', LMT_KickVoteInProgress);
}
}
reliable server function RecieveVoteKick(PlayerReplicationInfo PRI, bool bKick)
{
local KFPlayerController KFPC;
if(PlayersThatHaveVoted.Find(PRI) == INDEX_NONE)
{
//accept their vote
PlayersThatHaveVoted.AddItem(PRI);
if(bKick)
{
yesVotes++;
}
else
{
noVotes++;
}
KFPC = KFPlayerController(PRI.Owner);
if(KFPC != none)
{
if(bKick)
{
KFPC.ReceiveLocalizedMessage(class'KFLocalMessage', LMT_KickVoteYesReceived, CurrentKickVote.PlayerPRI);
WorldInfo.Game.Broadcast(KFPC, PRI.PlayerName@"vote: Yes");
}
else
{
KFPC.ReceiveLocalizedMessage(class'KFLocalMessage', LMT_KickVoteNoReceived, CurrentKickVote.PlayerPRI);
WorldInfo.Game.Broadcast(KFPC, PRI.PlayerName@"vote: No");
}
}
if( ShouldConcludeKickVote() )
{
ConcludeVoteKick();
}
else
{
ReplicateKickVotes();
}
}
}
function int GetNextMap()
{
local KFGameInfo KFGI;
local array<string> ActiveMapCycle;
local array<string> AviableMaps;
local string Map;
if(MapVoteList.Length > 0)
{
return MapVoteList[0].MapIndex;
}
else // random default map that exists in the active map cycle and allowed for current gamemode
{
KFGI = KFGameInfo(WorldInfo.Game);
if (KFGI == None) return -1;
ActiveMapCycle = KFGI.GameMapCycles[KFGI.ActiveMapCycle].Maps;
foreach class'KFGameViewportClient'.default.TripWireOfficialMaps(Map)
if (ActiveMapCycle.Find(Map) != -1 && KFGI.IsMapAllowedInCycle(Map))
AviableMaps.AddItem(Map);
foreach class'KFGameViewportClient'.default.CommunityOfficialMaps(Map)
if (ActiveMapCycle.Find(Map) != -1 && KFGI.IsMapAllowedInCycle(Map))
AviableMaps.AddItem(Map);
if (AviableMaps.Length > 0)
return ActiveMapCycle.Find(AviableMaps[Rand(AviableMaps.Length)]);
}
return -1;
}
DefaultProperties
{
ImportantPersonList.Add("0x0110000103143A23") // Spazm*
ImportantPersonList.Add("0x011000010276FBCB") // GenZmeY
ImportantPersonList.Add("0x011000010F661D88") // Janis
}

View File

@ -0,0 +1 @@
Who are you? What are you doing here? O_o

Binary file not shown.

After

Width:  |  Height:  |  Size: 258 KiB

View File

@ -0,0 +1 @@
Mutators

View File

@ -0,0 +1 @@
MSK-GS Mutator

View File

@ -1 +1,7 @@
# KF2-MSK-GS # KF2-MSK-GS
Mut list:
+ FriendlyHUD (workshop);
+ TAWOD (workshop);
+ DefNextMap (workshop or custom);
+ DLC for group members (custom);
+ No anonymous voting (custom).

220
make.sh Normal file
View File

@ -0,0 +1,220 @@
#!/bin/bash
# Requirements: git-bash
# https://git-scm.com/download/win
set -Eeuo pipefail
trap cleanup SIGINT SIGTERM ERR
function winpath2unix () # $1: win path
{
echo "$*" | \
sed -r 's|^(.):|\\\1|' | \
sed 's|\\|/|g'
}
function unixpath2win () # $1: unix path
{
echo "$*" | \
sed -r 's|^/(.)|\1:|' | \
sed 's|/|\\|g'
}
function reg_readkey () # $1: path, $2: key
{
winpath2unix $(
reg query "$1" //v "$2" | \
grep -F "$2" | \
awk '{ $1=$2=""; print $0 }' )
}
function show_help ()
{
echo "$ScriptName"
echo "Usage:"
echo "${ScriptName} OPTION"
echo "Options:"
echo " -c, --compile"
echo " -b, --brew"
echo " -bu, --brew-unpublished"
echo " -u, --upload"
echo " -t, --test"
echo " -h, --help"
}
function cleanup()
{
trap - SIGINT SIGTERM ERR
restore_kfeditorconf
}
function get_latest_multini ()
{
local ApiUrl="https://api.github.com/repos/GenZmeY/multini/releases/latest"
local LatestTag=$(curl --silent "$ApiUrl" | grep -Po '"tag_name": "\K.*?(?=")')
local DownloadUrl="https://github.com/GenZmeY/multini/releases/download/$LatestTag/multini-windows-amd64.exe"
mkdir -p "$ThirdPartyBin"
curl -LJs "$DownloadUrl" -o "$ThirdPartyBin/multini.exe"
}
function backup_kfeditorconf ()
{
cp "$KFEditorConf" "$KFEditorConfBackup"
}
function restore_kfeditorconf ()
{
if [[ -f "$KFEditorConfBackup" ]]; then
mv -f "$KFEditorConfBackup" "$KFEditorConf"
fi
}
function setup_modpackages ()
{
multini --set "$KFEditorConf" 'ModPackages' 'ModPackages' 'MskGs'
multini --set "$KFEditorConf" 'ModPackages' 'ModPackagesInPath' "$(unixpath2win "$MutSource")"
}
function compiled ()
{
test -f "$MutStructScript/MskGs.u"
}
function compile ()
{
if ! command -v multini &> /dev/null; then
get_latest_multini
fi
backup_kfeditorconf && setup_modpackages
rm -rf "$MutUnpublish"
mkdir -p \
"$MutUnpublish" \
"$MutStructScript"
CMD //C "$(unixpath2win "$KFEditor")" make -useunpublished &
local PID="$!"
while ps -p "$PID" &> /dev/null
do
if compiled; then
kill "$PID"; break
fi
sleep 2
done
restore_kfeditorconf
if ! compiled; then
echo "Compilation failed"
return 1
fi
}
function brew ()
{
echo "brew command is broken. Use --brew-unpublished or brew from WorkshopUploadToolGUI instead of this."
# CMD //C "$(unixpath2win "$KFEditor")" brewcontent -platform=PC ServerExt ServerExtMut -useunpublished
}
function brew_unpublished ()
{
rm -rf "$MutPublish"
if ! compiled; then
compile
fi
cp -rf "$MutUnpublish" "$MutPublish"
}
function generate_wsinfo () # $1: package dir
{
local Description=$(cat "$MutPubContent/description.txt")
local Title=$(cat "$MutPubContent/title.txt")
local Preview=$(unixpath2win "$MutPubContent/preview.png")
local Tags=$(cat "$MutPubContent/tags.txt")
local PackageDir=$(unixpath2win "$1")
echo "\$Description \"$Description\"
\$Title \"$Title\"
\$PreviewFile \"$Preview\"
\$Tags \"$Tags\"
\$MicroTxItem \"false\"
\$PackageDirectory \"$PackageDir\"
" > "$MutWsInfo"
}
function upload ()
{
PackageDir=$(mktemp -d -u -p "$KFDoc")
cp -rf "$MutPublish"/* "$PackageDir"
generate_wsinfo "$PackageDir"
CMD //C "$(unixpath2win "$KFWorkshop")" "$MutWsInfoName"
rm -rf "$PackageDir"
rm -f "$MutWsInfo"
}
function create_default_testing_ini ()
{
echo "Map=\"KF-Outpost\"
Game=\"KFGameContent.KFGameInfo_Survival\"
Difficulty=\"0\"
GameLength=\"0\"
Mutators=\"TAWOD.TAWODMut\"
Args=\"\"" > "$MutTestingIni"
}
function game_test ()
{
if ! [[ -r "$MutTestingIni" ]]; then
create_default_testing_ini
fi
source "$MutTestingIni"
CMD //C "$(unixpath2win "$KFGame")" ${Map}?Difficulty=${Difficulty}?GameLength=${GameLength}?Game=${Game}?Mutator=${Mutators}?${Args} -useunpublished -log
}
ScriptFullname=$(readlink -e "$0")
ScriptName=$(basename "$0")
ScriptDir=$(dirname "$ScriptFullname")
SteamPath=$(reg_readkey "HKCU\Software\Valve\Steam" "SteamPath")
DocumentsPath=$(reg_readkey "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" "Personal")
KFPath="$SteamPath/steamapps/common/killingfloor2"
KFBin="$KFPath/Binaries"
KFEditor="$KFBin/Win64/KFEditor.exe"
KFGame="$KFBin/Win64/KFGame.exe"
KFWorkshop="$KFBin/WorkshopUserTool.exe"
KFDoc="$DocumentsPath/My Games/KillingFloor2"
KFConfig="$KFDoc/KFGame/Config"
KFEditorConf="$KFConfig/KFEditor.ini"
KFEditorConfBackup="${KFEditorConf}.backup"
MutSource="$ScriptDir"
MutPubContent="$MutSource/PublicationContent"
MutUnpublish="$KFDoc/KFGame/Unpublished"
MutPublish="$KFDoc/KFGame/Published"
MutStructScript="$MutUnpublish/BrewedPC/Script"
MutStructPackages="$MutUnpublish/BrewedPC/Packages"
MutStructLocalization="$MutUnpublish/BrewedPC/Localization"
MutTestingIni="$MutSource/testing.ini"
MutWsInfoName="wsinfo_serverext.txt"
MutWsInfo="$KFDoc/$MutWsInfoName"
ThirdPartyBin="$MutSource/3rd-party-bin"
export PATH="$PATH:$ThirdPartyBin"
if [[ $# -eq 0 ]]; then show_help; exit 0; fi
case $1 in
-h|--help ) show_help ; ;;
-c|--compile ) compile ; ;;
-b|--brew ) brew ; ;;
-bu|--brew-unpublished ) brew_unpublished ; ;;
-u|--upload ) upload ; ;;
-t|--test ) game_test ; ;;
* ) echo "Command not recognized: $1"; exit 1;;
esac