Skip to content

Instantly share code, notes, and snippets.

@w1lla
Created December 23, 2014 18:38
Show Gist options
  • Save w1lla/3da41dc0d204fdd001c6 to your computer and use it in GitHub Desktop.
Save w1lla/3da41dc0d204fdd001c6 to your computer and use it in GitHub Desktop.
DoubleDown ShootMania ManiaScript
//***********************************************************
//-| Mode: Double Down (Meltdown)
//-| Author: SMTRAK.Kadaz.Knight
//-| Contact: straightcue@gmail.com
//-| Aid Contribute: steeffeen\kak0\lethan\djhubertus\w1lla\
//***********************************************************
#Extends "Modes/ShootMania/ModeBase.Script.txt"
#Const CompatibleMapTypes "MeleeArena"
#Const Version "2014-11-28"
#Const ScriptName "Melee.Script.txt"
#Include "MathLib" as MathLib
#Include "TextLib" as TextLib
#Include "Libs/Nadeo/Color.Script.txt" as Color
#Include "Libs/Nadeo/Layers2.Script.txt" as Layers
#Include "Libs/Nadeo/Message.Script.txt" as Message
#Include "Libs/Nadeo/ShootMania/SM.Script.txt" as SM
#Include "Libs/Nadeo/Settings.Script.txt" as Settings
#Include "Libs/Nadeo/Interface.Script.txt" as Interface
#Include "Libs/Nadeo/ShootMania/Score.Script.txt" as Score
#Include "Libs/Nadeo/ShootMania/SpawnScreen.Script.txt" as SpawnScreen
#Include "Libs/Nadeo/ShootMania/ScoresTable.Script.txt" as ScoresTable
// Menu Values
#Setting S_TimeLimit 900 as _("$dddTime limit:")
#Setting S_PointsLimit 75 as _("$dddPoints limit:")
#Setting S_BotPower 4. as _("$dddBot Strength: ($f800$ddd=Random) or ($f801$ddd-$f8010$ddd)")
#Setting S_AddinBots 7 as _("$dddNumber of Shootmania Bots: ($f801$ddd-$f8025$ddd)")
#Setting S_Mode 0 as _("$dddMode: $f801$ddd: Default $f802$ddd: InstaShot $f803$ddd: UltraSkeet")
#Setting S_WeaponNumber 1 as _("$f800$ddd: Random $f801$ddd: Rocket $f802$ddd: Laser $f803$ddd: Nucleus $f804$ddd: Arrow")
#Setting S_EndMapChatTime 20 as "<hidden>"
#Setting S_SpawnProtect 5 as "<hidden>"
#Setting S_BotRewards True as _("$dddReceive points for hitting Bots.")
#Setting S_TurretBots False as _("$dddBot Force: Turret Bots.$i$555Disabled") // Botplayers.driver line 900+
#Setting S_TeamMode False as _("$dddTeam Mode: Clan Matches.$i$555Disabled")
#Setting S_CoopMode False as _("$dddCoop Mode: Humans Vs Bots.$i$555Disabled")
#Setting S_ItemMode False as _("$dddPickups: Enhanced Collectables.$i$555Disabled")
#Setting S_BotMode 0 as _("$555Bots Weapons: Random. Rocket. Laser. Nucleus. Arrow.")
#Setting S_Note True as _("\n\n$s$ddd》 Welcome to $000Knight$fff'$000s $f10Melee $dddVoting Menu:\n\n》 If you want to donate planets, login: smrock.\n\n》 Be considerate when voting, inform about changes.\n\n》 Any Suggestions, Comments, Help Welcomed.\n\n》 Ephesians 6:10-18.")
//#Setting S_AutoManageAFK False as "<hidden>"
//#Setting Notes: Double down the glide effect (0.5) and double up the amount of stamina. (2.0)
//#Setting Notes: To have the server automatically reset to defaults when the last person leaves.
// Constant Parameters
#Const C_NbBots 5
#Const C_ERollTime 3000
#Const BotStuckRestart 5000 //havn't done the code for it yet.
#Const C_AutoSwitchWeapon True
#Const C_NeutralEmblemUrl "https://www.cx.com/0/io/hotlink/CCezthP9EeOQ9hICPSHM9A/Kn.dds"
#Const C_RocketSelfDamage True //get these three damages working properly..
#Const C_NucleusSelfDamage True
#Const C_ArrowSelfDamage True
//#Const C_NbTurrentBotskin "https://Skins/Models/ArenaPlayer/robot.zip" // Give the Bots a separate model.
#Const Description _("$f90$wOBJECTIVE:$m$i$bbb - Keep the Game Enjoyable. Will the Best to Win.$i\n\n$f90$wMODE TYPES:$m $i$bbb- Server Default or Select|Vote Custom Mode.$i\n $f201$bbb. $uDefault$u - Double Down's Shootmania Player mode, all regular settings.\n $f202$bbb. $uInstaShot$u - Spawn with Weapon#, Instant elimination on 1 shot.\n $f203$bbb. $uUltraSkeet$u - Spawn with Weapon#, Equipped with Repetitious Shots, 8 Armors.\n $f204$333. $uPower Bots $u - Spawn Higher Power bots, armed with Power Weapons.\n\n$f90$wRULESET:$m $bbb$i- There is an filter log, so be bad, and get booted, pm-ban.$i\n $f201$bbb. $uCode of Conduct$u - Be polite, means no cursing, swearing, trash talking, etc.\n $f202$bbb. $uManner of Respect$u - If gamers are ok with the mode, don't try force changes.\n $f203$bbb. $uGamer Conscientious $u - Children do play here, so respect the gameplay.\n $f204$bbb. $uAuthority Rules$u - Have a question, feel free ask, don't assume the rules.\n\n$w$s$07fOne for All, All for One.")
// Global Variables
declare Ident G_LeaderId;
declare Ident[] G_SpawnsList;
declare Text G_LongestRollName;
declare Integer G_LongestRollNumber;
// Extends Versions
***LogVersion***
***
MB_LogVersion(ScriptName, Version);
MB_LogVersion(SM::GetScriptName(), SM::GetScriptVersion());
MB_LogVersion(Score::GetScriptName(), Score::GetScriptVersion());
MB_LogVersion(Message::GetScriptName(), Message::GetScriptVersion());
MB_LogVersion(Interface::GetScriptName(), Interface::GetScriptVersion());
MB_LogVersion(ScoresTable::GetScriptName(), ScoresTable::GetScriptVersion());
MB_LogVersion(SpawnScreen::GetScriptName(), SpawnScreen::GetScriptVersion());
***
***StartServer***
***
// Set mode options
UseClans = False;
UsePlayerTagging = True;
ForceNavMapsComputation = True;
ModeStatusMessage = _("$fffSM MODES: $cccClassic/Instashot/UltraSkeet \n$fffSM TYPE: $cccFFA DM Rocket/Laser/Arrow/Nukes \n$fffRULESET: $cccRead the rules at Spawn Screen, press (F1) \n$2f0SMTRAK Message: $cccDo $fffRESET $cccto defaults when exit.");
// Initialize UI
SpawnScreen::SetModeName("MeltDown");
SpawnScreen::ResetRulesSection();
SpawnScreen::AddSubsection(_(""), Description^"", 5.);
SpawnScreen::CreatePrettyRules("Meltdown");
SpawnScreen::CreateScores();
SpawnScreen::CreateMapInfo();
Interface::CreateRank();
UpdateScoresHeader();
// ScoresTable
declare Text BGImage = "file://Media/Manialinks/ShootMania/Common/topsBg.dds"; // a lighter colour or a custom image?
declare Text BGImageFull = "file://Media/Manialinks/ShootMania/Common/scoresBg.dds";
declare Text BGImgLeft = "file://Media/Manialinks/ShootMania/Common/scoresBg_left.dds";
declare Text BGImgRight = "file://Media/Manialinks/ShootMania/Common/scoresBg_right.dds";
ScoresTable::Load();
ScoresTable::SetTableWidth(220.0);
ScoresTable::SetTableFormat(2, 7);
ScoresTable::SetTableBackgroundImage(BGImage, <0.05, 60.>, <240., 195.>);
ScoresTable::SetColumnsWidth(1.7, 1.2, 3., 16., 1.4, 1.4, 0.3, 4., 0., 2.5, 3.2);
ScoresTable::SetColumnName("Custom2", _("|Accuracy|Accuracy"));
ScoresTable::SetColumnName("RoundPoints", _("|Consecutive Hits|Roll"));
ScoresTable::SetColumnName("Points", _("|Total Points|Points"));
ScoresTable::SetRoundScoreFormat("$s$3c0");
ScoresTable::Build();
UpdateScoresHeader();
***
***StartMap***
***
Users_SetNbFakeUsers(C_NbBots, 0);
G_SpawnsList.clear();
Score::MatchBegin();
SM::SetupDefaultVisibility();
// Init bases
foreach (Base in MapBases) {
Base.Clan = 0;
Base.IsActive = True;
}
// Init scores
Score::MatchBegin();
ScoresTable::StartMatch();
foreach (Score in Scores) {
declare Integer LastPoint for Score;
LastPoint = 0;
InitScore(Score);
}
G_LeaderId = NullId;
G_LongestRollNumber = 0;
UpdateScoresHeader();
StartTime = Now;
EndTime = StartTime + S_TimeLimit * 1000;
UIManager.UIAll.UISequence = CUIConfig::EUISequence::Playing;
declare CurrentTimeLimit = S_TimeLimit;
// Enter Server Messages - testing.. doesnt work..
//UI.ManialinkPage = """//{{{Now}}}
// <audio looping="0" hidden="1" play="1" data="http://file.url.welsound.org"/>""";
UIManager.UIAll.SendNotice(_("$fffPlaying on $w$000Ҡnight$fff'$000s$fc2 $f10Melee $dddUS Server."),
CUIConfig::ENoticeLevel::Default, Null, CUIConfig::EAvatarVariant::Happy, CUIConfig::EUISound::Bonus, 1);
// Map Enter Messages - make it an ingame Media Tracker animation or no?
Message::SendBigMessage("$w$s$f20< $cccBeta Testing $f20>", 1000, 1500, CUIConfig::EUISound::Silence, 0);
UIManager.UIAll.SendChat("""$ddd» $0af$sMelee Enhanced $dddv3.4+""");
UIManager.UIAll.SendChat("""$ddd» $390$sSupport Holiday Giving $ddd$lhttp://giving-gamers.com""");
UIManager.UIAll.SendNotice(_("$w$s$f20Let the Fun Begin$ddd."),
CUIConfig::ENoticeLevel::Default, Null, CUIConfig::EAvatarVariant::Happy, CUIConfig::EUISound::Silence, 1);
UIManager.UIAll.SendNotice(_("$ddd$sMatch has Started $07f..."),
CUIConfig::ENoticeLevel::Default, Null, CUIConfig::EAvatarVariant::Default, CUIConfig::EUISound::StartMatch, 1);
***
***InitRound***
***
declare Boolean MyVariable = False;
***
***OnNewPlayer***
***
InitPlayer(Player, False);
SetFooterStats(Player);
***
***OnNewSpectator***
***
InitPlayer(Spectator, False);
SetFooterStats(Spectator);
***
***PlayLoop***
***
// Check for setting update
CheckSettings();
//AFK::ManageAFKPlayers (S_MaxIdleDuration * 1000, 0);
// Handle events
foreach (Event in PendingEvents) {
switch (Event.Type) {
case CSmModeEvent::EType::OnArmorEmpty: {
if (Event.Shooter == Event.Victim || Event.Shooter == Null) {
AddPoints(Event.Victim, -1);
ShowPenaltyInfo(Event.Victim, 1, "SelfElimination", False);
} else {
if (Event.Shooter.Score != Null) {
declare CurrentEliminationNb for Event.Shooter.Score = 0;
CurrentEliminationNb += 1;
}
if (!Event.Shooter.IsFakePlayer) {
XmlRpc::OnArmorEmpty(Event);
}
}
PassOn(Event);
}
case CSmModeEvent::EType::OnHit: {
declare Points = 1;
if (Event.Shooter == Null || Event.Victim == Null) {
Discard(Event);
continue;
}
if (Event.Shooter == Event.Victim) {
Event.Damage = 30;
ShowPenaltyInfo(Event.Shooter, 1, "Warning", False);
}
//if (C_RocketSelfDamage && Event.WeaponNum == This.GetWeaponIndex(CSmMode::EWeapon::Rocket)+1) {
//Event.Damage = 30;
//}
//if (C_NucleusSelfDamage && Event.WeaponNum == This.GetWeaponIndex(CSmMode::EWeapon::Nucleus)+1) {
///Event.Damage = 50;
//}
//if (C_ArrowSelfDamage && Event.WeaponNum == This.GetWeaponIndex(CSmMode::EWeapon::Arrow)+1) {
//Event.Damage = 70;
//}
if (Event.Shooter == Event.Victim)
Points -= 1;
Event.ShooterPoints = Points;
Score::AddPoints(Event.Shooter, Points);
if (Event.Victim.IsFakePlayer && !S_BotRewards) Points = 0;
//if (Event.Shooter && !S_CoopMode) Event.Damage = 0; Points = 0;
//_Player.Driver.AttackFilter = CSmPlayerDriver::ESmAttackFilter::OppositeBots;
if (Event.Shooter.Score != Null) {
if (Event.Victim.Armor <= Event.Damage) {
// Victim will be eliminated - Handle Eliminationroll
declare LastEliminationTimes for Event.Shooter.Score = Integer[Integer];
if (LastEliminationTimes.count > 0) {
if (LastEliminationTimes[LastEliminationTimes.count-1] + C_ERollTime > Now) {
// Consecutive Elimination roll
LastEliminationTimes[LastEliminationTimes.count] = Now;
Points *= LastEliminationTimes.count;
Message::SendStatusMessage(Event.Shooter, TextLib::Compose(_("EliminationRoll #%1!"),
TextLib::ToText(LastEliminationTimes.count)), 2300, 0);
} else {
// Too slow!
LastEliminationTimes.clear();
}
} else {
// Begin Elimination roll
LastEliminationTimes[0] = Now;
}
}
declare CurrentHitNb for Event.Shooter.Score = 0;
CurrentHitNb += 1;
UpdateHitrate(Event.Shooter);
}
AddPoints(Event.Shooter, Points);
Event.ShooterPoints = Points;
// Check for longest roll
if (Event.Shooter.Score != Null && Event.Shooter.Score.RoundPoints > G_LongestRollNumber) {
G_LongestRollNumber = Event.Shooter.Score.RoundPoints;
G_LongestRollName = Event.Shooter.Name;
SetFooterStats(Null);
}
// Play sound and notice if someone is close to win
if (Event.Shooter != Null && Event.Shooter.Score != Null) {
declare LastPoint for Event.Shooter.Score = 0;
declare Gap = S_PointsLimit - Event.Shooter.Score.Points;
if (Gap > 0 && Gap <= 3) {
declare Variant = 3 - Gap;
declare Msg = "";
if (Gap > 1) Msg = TextLib::Compose(_("$<%1$>$ddd is %2 pts from ending the map $f20$w!"),
Event.Shooter.Name, TextLib::ToText(Gap));
else Msg = TextLib::Compose(_("$<%1$>$ddd is 1 pt from final elimination $f20$w!"), Event.Shooter.Name);
Message::SendStatusMessage(Msg, 2000, 0, CUIConfig::EUISound::TieBreakPoint, Variant);
} else if (Gap <= 0) {
Message::SendStatusMessage(TextLib::Compose(_("$<%1$>$ddd has finished Victorious $f20$w!"), Event.Shooter.Name), 2000, 0, CUIConfig::EUISound::VictoryPoint, 0);
}
if (!Event.Shooter.IsFakePlayer) {
XmlRpc::OnHit(Event);
}
PassOn(Event);
}
}
case CSmModeEvent::EType::OnPlayerRequestRespawn: {
if (Event.Player == Null) {
Discard(Event);
} else {
AddPoints(Event.Player, -1);
ShowPenaltyInfo(Event.Player, 1, "RequestRespawn", False);
if (!Event.Player.IsFakePlayer) {
XmlRpc::OnPlayerRequestRespawn(Event);
}
PassOn(Event);
}
}
case CSmModeEvent::EType::OnShoot: {
if (Event.Shooter == Null) {
Discard(Event);
} else {
if (Event.Shooter.Score != Null) {
declare CurrentShotNb for Event.Shooter.Score = 0;
CurrentShotNb += 1;
UpdateHitrate(Event.Shooter);
}
if (!Event.Shooter.IsFakePlayer) {
XmlRpc::OnShoot(Event);
}
PassOn(Event);
}
}
default: {
// Others
PassOn(Event);
}
}
}
// Spawn players
foreach (Player in Players) {
if (Player.SpawnStatus == CSmPlayer::ESpawnStatus::NotSpawned && !Player.RequestsSpectate) {
MeleeSpawnPlayer(Player);
}
}
// Manage bots
ManageBots();
// Play sound and notice if someone is taking the lead
if (Scores.existskey(0) && Scores[0].Points > 0 && Scores[0].Id != G_LeaderId) {
G_LeaderId = Scores[0].Id;
UIManager.UIAll.SendNotice(TextLib::Compose(_("$<%1$>$ddd takes lead point $f20$w..."), Scores[G_LeaderId].User.Name),
CUIConfig::ENoticeLevel::Default, Null, CUIConfig::EAvatarVariant::Default, CUIConfig::EUISound::FirstHit, 1);
---ModeStatusMessage---
}
// Update time limit
if (CurrentTimeLimit != S_TimeLimit) {
CurrentTimeLimit = S_TimeLimit;
if (S_TimeLimit > 0) EndTime = StartTime + (S_TimeLimit * 1000);
else EndTime = -1;
}
Message::Loop();
// Victory conditions
if (Now > EndTime) {
MB_StopMap = True;
} else {
foreach (Score in Scores) {
if (Score.Points >= S_PointsLimit) {
MB_StopMap = True;
}
}
}
***
***EndMap***
***
StartTime = -1;
EndTime = -1;
Score::MatchEnd();
ScoresTable::EndMatch();
UIManager.UIAll.SendNotice(_("$ddd$sMatch is Finished $07f..."),
CUIConfig::ENoticeLevel::MapInfo, Null, CUIConfig::EAvatarVariant::Default, CUIConfig::EUISound::Finish, 1);
// End match sequence
declare CSmScore Winner <=> Null;
declare WinnerPoints = 0;
declare MarkStat = 0;
foreach (Score in Scores) {
if (Score.Points > WinnerPoints) {
WinnerPoints = Score.Points;
Winner <=> Score;
} else {
if (Score.Points == WinnerPoints) {
if (GetHitrate(Score) > GetHitrate(Winner)) {
WinnerPoints = Score.Points;
Winner <=> Score;
MarkStat = 1;
} else {
if (GetHitrate(Score) == GetHitrate(Winner)) {
Winner <=> Null;
}
}
}
}
}
foreach (Player in Players) {
if (Player.Score != Winner) {
UnspawnPlayer(Player);
} else {
switch (MarkStat) {
case 1: {
UpdateHitrate(Player, True);
}
}
}
Interface::UpdatePosition(Player);
}
declare DisplayTime = (S_EndMapChatTime * 1000) / 2;
MB_Sleep(1000);
Message::CleanAllMessages();
if (Winner != Null && Winner.User != Null) {
UIManager.UIAll.BigMessage = TextLib::Compose(_("$<%1$>$ddd wins the match $f20$w!"), Winner.User.Name);
} else {
UIManager.UIAll.BigMessage = _("$03f<<$ddd Match Draw $03f>>");
}
MB_Sleep(1000);
UIManager.UIAll.UISequence = CUIConfig::EUISequence::EndRound;
UIManager.UIAll.ScoreTableVisibility = CUIConfig::EVisibility::ForcedVisible;
This.DestroyAllBotPlayers();
MB_Sleep(3500);
UIManager.UIAll.UISequence = CUIConfig::EUISequence::Podium;
wait(UIManager.UIAll.UISequenceIsCompleted);
UIManager.UIAll.ScoreTableVisibility = CUIConfig::EVisibility::Normal;
***
***EndServer***
***
ScoresTable::Unload();
Interface::DestroyRank();
SpawnScreen::DestroyRules();
SpawnScreen::DestroyScores();
SpawnScreen::DestroyMapInfo();
***
// Functions
// Update the scores header
Void UpdateScoresHeader() {
UIManager.UIAll.OverlayScoreSummary = True;
declare G_LeaderId = NullId;
foreach (Player in Players) {
if ((G_LeaderId == NullId) && (Player.CurrentClan == 1)) G_LeaderId = Player.Id;
if ((G_LeaderId == NullId) && (Player.CurrentClan == 2)) G_LeaderId = Player.Id;
if (G_LeaderId != NullId && G_LeaderId != NullId) break;
}
if (G_LeaderId != NullId) UIManager.UIAll.ScoreSummary_Player1 = G_LeaderId;
else UIManager.UIAll.ScoreSummary_Player1 = NullId;
if (G_LeaderId != NullId) UIManager.UIAll.ScoreSummary_Player2 = G_LeaderId;
else UIManager.UIAll.ScoreSummary_Player2 = NullId;
UIManager.UIAll.ScoreSummary_MatchPoints1 = -1;
UIManager.UIAll.ScoreSummary_MatchPoints2 = -1;
}
// Set footer score on the scoreboard for the given player
Void SetFooterScore(CSmPlayer _Player) {
if (_Player == Null || _Player.Score == Null) return;
ScoresTable::SetFooterScore(_Player, TextLib::Compose(_("〘$s$ccc Be of $09fGood Cheer $ccc& $09fStrong Courage $ccc〙"),
TextLib::ToText(_Player.Score.RoundPoints)));
}
// Set footer stats on the scoreboard for the given player
Void SetFooterStats(CSmPlayer _Player) {
if (_Player == Null) {
foreach (Player in AllPlayers) {
SetFooterStats(Player);
}
} else {
declare Message = "";
if (G_LongestRollNumber > 0) {
Message = TextLib::Compose(_("Longest Elimination Roll: %1 by $<%2$> Current Points Limit: %3"),
TextLib::ToText(G_LongestRollNumber), G_LongestRollName,
TextLib::ToText(S_PointsLimit));
} else {
Message = TextLib::Compose(_("Current Points Limit: %1"), TextLib::ToText(S_PointsLimit));
}
ScoresTable::SetFooterStats(_Player, Message);
}
}
// Add points to current and total points
Void AddPoints(CSmPlayer _Player, Integer _Points)
{
_Player.Score.Points += _Points;
}
Void ShowPenaltyInfo(CSmPlayer _Player, Integer _Penalty, Text _PenaltyText, Boolean DisplayBigMessage)
{
if (_PenaltyText == "SelfElimination"){
if(_Player == Null) {
UIManager.UIAll.SendNotice(
TextLib::Compose(_("$f20Self Elimination Penalty: $ccc-%1"), TextLib::ToText(_Penalty)), CUIConfig::ENoticeLevel::MatchInfo,
Null, CUIConfig::EAvatarVariant::Default,
CUIConfig::EUISound::Silence, 0);
} else {
declare UI <=> UIManager.GetUI(_Player);
if (UI != Null) {
if(!DisplayBigMessage) {
UI.SendNotice(
TextLib::Compose(_("$f20Self Elimination Penalty: $ccc-%1"), TextLib::ToText(_Penalty)), CUIConfig::ENoticeLevel::PlayerInfo,
Null, CUIConfig::EAvatarVariant::Default,
CUIConfig::EUISound::Silence, 0);
} else {
UI.SendNotice(
TextLib::Compose(_("$f20Self Elimination Penalty: $ccc-%1"), TextLib::ToText(_Penalty)), CUIConfig::ENoticeLevel::MatchInfo,
Null, CUIConfig::EAvatarVariant::Default,
CUIConfig::EUISound::Silence, 0);
}
}
}
}
if (_PenaltyText == "RequestRespawn"){
if(_Player == Null) {
UIManager.UIAll.SendNotice(
TextLib::Compose(_("$f20Respawn Penalty: $ccc-%1"), TextLib::ToText(_Penalty)), CUIConfig::ENoticeLevel::MatchInfo,
Null, CUIConfig::EAvatarVariant::Default,
CUIConfig::EUISound::Silence, 0);
} else {
declare UI <=> UIManager.GetUI(_Player);
if (UI != Null) {
if(!DisplayBigMessage) {
UI.SendNotice(
TextLib::Compose(_("$f20Respawn Penalty: $ccc-%1"), TextLib::ToText(_Penalty)), CUIConfig::ENoticeLevel::PlayerInfo,
Null, CUIConfig::EAvatarVariant::Default,
CUIConfig::EUISound::Silence, 0);
} else {
UI.SendNotice(
TextLib::Compose(_("$f20Respawn Penalty: $ccc-%1"), TextLib::ToText(_Penalty)), CUIConfig::ENoticeLevel::MatchInfo,
Null, CUIConfig::EAvatarVariant::Default,
CUIConfig::EUISound::Silence, 0);
}
}
}
}
if (_PenaltyText == "Warning"){
if(_Player == Null) {
UIManager.UIAll.SendNotice(
TextLib::Compose(_("$f90Caution$ccc..."), TextLib::ToText(_Penalty)), CUIConfig::ENoticeLevel::MatchInfo,
Null, CUIConfig::EAvatarVariant::Default,
CUIConfig::EUISound::Silence, 0);
} else {
declare UI <=> UIManager.GetUI(_Player);
if (UI != Null) {
if(!DisplayBigMessage) {
UI.SendNotice(
TextLib::Compose(_("$f90Caution$ccc..."), TextLib::ToText(_Penalty)), CUIConfig::ENoticeLevel::PlayerInfo,
Null, CUIConfig::EAvatarVariant::Default,
CUIConfig::EUISound::Silence, 0);
} else {
UI.SendNotice(
TextLib::Compose(_("$f90Caution$ccc..."), TextLib::ToText(_Penalty)), CUIConfig::ENoticeLevel::MatchInfo,
Null, CUIConfig::EAvatarVariant::Default,
CUIConfig::EUISound::Silence, 0);
}
}
}
}
}
// Get hitrate of a player
Integer GetHitrate(CSmScore _Score) {
if (_Score == Null) return -1;
declare CurrentShotNb for _Score = 0;
declare CurrentHitNb for _Score = 0;
if (CurrentShotNb > 0) {
declare Hitrate = (CurrentHitNb * 1.0) / (CurrentShotNb * 1.0);
if (Hitrate > 0.0) {
return MathLib::NearestInteger(Hitrate*100.0);
}
}
return -1;
}
// Update hitrate on the scorestable
Void UpdateHitrate(CSmPlayer _Player, Boolean _Highlight) {
if (_Player == Null) return;
declare Hitrate = GetHitrate(_Player.Score);
if (Hitrate > 0) {
if (_Highlight) {
ScoresTable::SetCustom2(_Player, "$s$o$0f0"^TextLib::ToText(Hitrate)^"%");
} else {
ScoresTable::SetCustom2(_Player, TextLib::ToText(Hitrate)^"%");
}
} else {
ScoresTable::SetCustom2(_Player, "");
}
}
Void UpdateHitrate(CSmPlayer _Player) {
UpdateHitrate(_Player, False);
}
// Get winrate of a player
Real GetWinrate(CSmPlayer _Player) {
if (_Player == Null || _Player.Score == Null) return -1.;
declare CurrentSpawnNb for _Player.Score = 0;
declare CurrentEliminationNb for _Player.Score = 0;
if (CurrentSpawnNb > 0) {
declare Winrate = (CurrentEliminationNb * 1.0) / (CurrentSpawnNb * 1.0);
if (Winrate > 0.0) {
return MathLib::NearestInteger(Winrate * 100.0) / 100.0;
}
}
return -1.;
}
// Get the currently used weapon
CSmMode::EWeapon GetWeapon() {
declare WeaponNumber = S_WeaponNumber;
if (WeaponNumber < 1 || WeaponNumber > 4) {
// Random weapon
WeaponNumber = MathLib::Rand(1, 4);
}
// Return weapon
switch (WeaponNumber) {
case 2: {
return CSmMode::EWeapon::Laser;
}
case 3: {
return CSmMode::EWeapon::Nucleus;
}
case 4: {
return CSmMode::EWeapon::Arrow;
}
}
return CSmMode::EWeapon::Rocket;
}
// Get whether weapons should be switched automatically
Boolean GetAutoSwitchWeapon(CSmMode::EWeapon _Weapon) {
return (C_AutoSwitchWeapon || _Weapon == CSmMode::EWeapon::Rocket);
}
// Initialize the given score
Void InitScore(CSmScore _Score) {
if (_Score == Null) return;
declare Integer CurrentShotNb for _Score;
declare Integer CurrentHitNb for _Score;
declare Integer CurrentSpawnNb for _Score;
declare Integer CurrentEliminationNb for _Score;
CurrentShotNb = 0;
CurrentHitNb = 0;
CurrentSpawnNb = 0;
CurrentEliminationNb = 0;
}
// Initialize values for a Player
Void InitPlayer(CSmPlayer _Player, Boolean _ForceResetScore) {
if (_Player == Null) return;
_Player.Armor = 300;
_Player.ArmorGain = 3;
_Player.ArmorMax = 400;
_Player.AmmoGain = 1.75;
_Player.AmmoPower = 1.5;
_Player.StaminaGain = 1.0;
_Player.StaminaMax = 3.0;
_Player.EnergyLevel = 1.0;
_Player.SpeedPower = 1.0;
_Player.ArmorReplenishGain = 1;
_Player.ForceColor = <0.0, 0.0, 0.0>;
SetPlayerAmmoMax(_Player, CSmMode::EWeapon::Laser, 1);
SetPlayerAmmoMax(_Player, CSmMode::EWeapon::Rocket, 4);
SetPlayerAmmoMax(_Player, CSmMode::EWeapon::Arrow, 3);
SetPlayerAmmoMax(_Player, CSmMode::EWeapon::Nucleus, 3);
SetPlayerWeapon(_Player, CSmMode::EWeapon::Rocket, True);
//SetWeaponRefire(Player, CSmMode::EWeapon::Nucleus, 5.0??);
// Apply Behaviour for Bot Player
if (_Player.Driver != Null) {
_Player.Driver.AttackFilter = CSmPlayerDriver::ESmAttackFilter::AllPlayers;
_Player.Driver.Behaviour = CSmPlayerDriver::ESmDriverBehaviour::Saunter;
//_Player.Driver.Saunter_AnchorPoint (Vec3) = AnchorPoint.;
_Player.Driver.Saunter_Radius = 1111.;
_Player.Driver.Saunter_BaseChillingTime = 11;
_Player.Driver.Saunter_ChillingTimeDelta = 0;
_Player.Driver.RocketAnticipation = True;
}
// Reset statistics
ScoresTable::RestoreCustomScores(_Player);
declare MyNewPlayer for _Player = True;
if (MyNewPlayer || _ForceResetScore) {
MyNewPlayer = False;
InitScore(_Player.Score);
}
UpdateHitrate(_Player);
SetFooterScore(_Player);
}
// Set Bot Power
Void SetBotPower(CSmPlayer _Player) {
if (_Player.IsFakePlayer) {
_Player.ForceColor = <.5, .0, .0>;
// Random Bot Power
declare RandomPower = (S_BotPower);
if (RandomPower == 0) {
_Player.ArmorMax = MathLib::Rand(100, 1000);
_Player.AmmoGain = MathLib::Rand(0.5, 5.0);
_Player.AmmoPower = MathLib::Rand(1.0, 4.0);
_Player.Driver.AggroRadius = MathLib::Rand(100., 1000.);
_Player.Driver.Fov = MathLib::Rand(0.36, 360.0);
_Player.Driver.ReactionTime = MathLib::Rand(50, 500);
_Player.Driver.Agressivity = MathLib::Rand(3.0, 10.0);
_Player.Driver.Accuracy = MathLib::Rand(3.0, 10.0);
_Player.Driver.ShootPeriodMin = MathLib::Rand(100, 900);
_Player.Driver.ShootPeriodMax = MathLib::Rand(300, 1100);
_Player.Driver.DisengageDistance = MathLib::Rand(200., 2000.);
//UIManager.UIAll.SendChat("""$f80Bot Strength is now $ddd"Random" $f20$w!"""); // make this stop repeating..
}
//To stop messages... Use at map start.. declare Boolean MyVariable = False;
//if (S_BotPower == 0 && !MyVariable) {
//UIManager.UIAll.SendChat("""$ddd Bot Strength is now "$cccRandom" $f20$w!""");
//MyVariable = True;
// ForceColor & ModeNumber, doesn't work, needs tweaking.
// declare ModeName = "";
// declare ForceColor = (S_BotPower);
// if (ForceColor = 10) {
// ForceColor = <1.0, .0, .0>;
// ModeNumber = "10";
// } else {
// if (ForceColor = 9) {
// ForceColor = <.9, .0, .0>;
// ModeNumber = "9";
// if (ForceColor = 8) {
// ForceColor = <.8, .0, .0>;
// ModeNumber = "8";
// if (ForceColor = 7) {
// ForceColor = <.7, .0, .0>;
// ModeNumber = "7";
// if (ForceColor = 6) {
// ForceColor = <.6, .0, .0>;
// ModeNumber = "6";
// if (ForceColor = 5) {
// ForceColor = <.5, .0, .0>;
// ModeNumber = "5";
// if (ForceColor = 4) {
// ForceColor = <.4, .0, .0>;
// ModeNumber = "4";
// if (ForceColor = 3) {
// ForceColor = <.3, .0, .0>;
// ModeNumber = "3";
// if (ForceColor = 2) {
// ForceColor = <.2, .0, .0>;
// ModeNumber = "2";
// if (ForceColor = 1) {
// ForceColor = <.2, .0, .0>;
// ModeNumber = "1";
// }
// }
// _Player.ForceColor = Forcecolor;
// if (S_ModNumber != 0) {
// UIManager.UIAll.SendChat("""$ddd Bot Strength is now "$ccc{{{ModeNumber}}}$ddd" $f20$w!"""); // make this stop repeating..
// EnergyLevel
declare EnergyLevel = (S_BotPower * 0.1 );
if (EnergyLevel > 1.0) {
EnergyLevel = 1.0;
} else {
if (EnergyLevel < 0.1) {
EnergyLevel = 0.1;
}
}
_Player.EnergyLevel = EnergyLevel;
// ArmorMax.i
declare ArmorMax = MathLib::NearestInteger(S_BotPower * 100);
if (ArmorMax > 1000) {
ArmorMax = 1000;
} else {
if (ArmorMax < 100) {
ArmorMax = 100;
}
}
_Player.ArmorMax = ArmorMax;
// AmmoGain.r
declare AmmoGain = S_BotPower * .5;
if (AmmoGain > 5.0) {
AmmoGain = 5.0;
} else if (AmmoGain < .5) {
AmmoGain = .5;
}
_Player.AmmoGain = AmmoGain;
// AmmoPower.r
declare AmmoPower = S_BotPower * 0.25;
if (AmmoPower > 4.) {
AmmoPower = 4.;
} else if (AmmoPower < 1.) {
AmmoPower = 1.;
}
_Player.AmmoPower = AmmoPower;
// AggroRadius.r
declare AggroRadius = S_BotPower * 100;
if (AggroRadius > 1000.) {
AggroRadius = 1000.;
} else {
if (AggroRadius < 100.) {
AggroRadius = 100.;
}
}
_Player.Driver.AggroRadius = AggroRadius;
// Fov.r
declare Fov = S_BotPower * 36;
if (Fov > 360.) {
Fov = 360.;
} else if (Fov < 36.) {
Fov = 36.;
}
_Player.Driver.Fov = Fov;
// ReactionTime.i
declare ReactionTime = MathLib::NearestInteger(S_BotPower * 50);
ReactionTime = 500 - ReactionTime;
if (ReactionTime > 500) {
ReactionTime = 500;
} else {
if (ReactionTime < 50) {
ReactionTime = 50;
}
}
_Player.Driver.ReactionTime = ReactionTime;
// Agressivity.r
declare Agressivity = S_BotPower;
if (Agressivity > 10.) {
Agressivity = 10.;
} else if (Agressivity < 1.) {
Agressivity = 1.;
}
_Player.Driver.Agressivity = Agressivity;
// Accuracy.r
declare Accuracy = S_BotPower;
if (Accuracy > 10.) {
Accuracy = 10.;
} else if (Accuracy < 1.) {
Accuracy = 1.;
}
_Player.Driver.Accuracy = Accuracy;
// ShootPeriodMin.i
declare ShootPeriodMin = MathLib::NearestInteger(S_BotPower * 80);
ShootPeriodMin = 900 - ShootPeriodMin;
if (ShootPeriodMin > 900) {
ShootPeriodMin = 900;
} else {
if (ShootPeriodMin < 100) {
ShootPeriodMin = 100;
}
}
_Player.Driver.ShootPeriodMin = ShootPeriodMin;
// ShootPeriodMax.i
declare ShootPeriodMax = MathLib::NearestInteger(S_BotPower * 80 );
ShootPeriodMax = 1100 - ShootPeriodMax;
if (ShootPeriodMax > 1100) {
ShootPeriodMax = 1100;
} else {
if (ShootPeriodMax < 300) {
ShootPeriodMax = 300;
}
}
_Player.Driver.ShootPeriodMax = ShootPeriodMax;
// DisengageDistance.r
declare DisengageDistance = S_BotPower * 200;
if (DisengageDistance > 2000.) {
DisengageDistance = 2000.;
} else {
if (DisengageDistance < 200.) {
DisengageDistance = 200.;
}
}
_Player.Driver.DisengageDistance = DisengageDistance;
}
}
// Spawn the given player
Void MeleeSpawnPlayer(CSmPlayer _Player) {
if (_Player.RequestsSpectate) return;
if (_Player.SpawnStatus == CSmPlayer::ESpawnStatus::Spawned) {
UnspawnPlayer(_Player);
}
// Reset Roll
if (_Player.Score != Null) {
declare LastEliminationTimes for _Player.Score = Integer[Integer];
LastEliminationTimes.clear();
_Player.Score.RoundPoints = 0;
declare CurrentSpawnNb for _Player.Score = 0;
CurrentSpawnNb += 1;
}
SetFooterScore(_Player);
// Set Bot Power
SetBotPower(_Player);
// Set Player Weapon
if (_Player.SpawnStatus != CSmPlayer::ESpawnStatus::Spawned) {
declare Weapon = GetWeapon();
This.SetPlayerWeapon(_Player, Weapon, GetAutoSwitchWeapon(Weapon));
// Set weapon depending values
switch (Weapon) {
case CSmMode::EWeapon::Rocket: {
}
case CSmMode::EWeapon::Laser: {
}
case CSmMode::EWeapon::Nucleus: {
}
case CSmMode::EWeapon::Arrow: {
}
}
}
if (G_SpawnsList.count == 0) {
foreach (BlockSpawn in MapLandmarks_PlayerSpawn) {
G_SpawnsList.add(BlockSpawn.Id);
}
}
declare SpawnId = NullId;
declare LatestSpawnId for This = NullId;
while (True) {
SpawnId = G_SpawnsList[MathLib::Rand(0, G_SpawnsList.count - 1)];
if (SpawnId != LatestSpawnId) break;
if (G_SpawnsList.count == 1) break;
}
LatestSpawnId = SpawnId;
if (_Player.Driver != Null) {
_Player.Driver.Saunter_AnchorPoint = MapLandmarks_PlayerSpawn[SpawnId].Position;
}
SM::SpawnPlayer(_Player, 0, MapLandmarks_PlayerSpawn[SpawnId].PlayerSpawn);
}
// Apply Behaviour for Internal Bot Players
Void VSpawnBot(CSmScriptBotPath Spawn)
{
//declare BotPlayer = CreateBotPlayer(NullId, 0, 100, Spawn, -1);
//SetPlayerWeapon(BotPlayer, CSmMode::EWeapon::Laser, True);
//assert (BotPlayer != Null && BotPlayer.Driver != Null);
//BotPlayer.Driver.Behaviour = CSmPlayerDriver::ESmDriverBehaviour::Saunter;
//BotPlayer.Driver.Patrol_Mode = CSmPlayerDriver::ESmDriverPatrolMode::Loop;
//BotPlayer.Driver.ShootPeriodMin = 100;
//BotPlayer.Driver.ShootPeriodMax = 1000;
//BotPlayer.Driver.Accuracy = 10.;
//BotPlayer.Driver.ReactionTime = 100;
//BotPlayer.Driver.RocketAnticipation = True;
//BotPlayer.Driver.DisengageDistance = 100.;
//BotPlayer.Driver.AggroRadius = 100.;
//BotPlayer.EnergyLevel = 1.;
//BotPlayer.SpeedPower = 1.;
}
// Manage adding and removing of bots
Void ManageBots() {
declare LastBotCheck for This = 0;
if (LastBotCheck + 10000 > Now) return;
LastBotCheck = Now;
// Collect bots
declare BotUserIds = Ident[];
foreach (Player in AllPlayers) {
if (Player.IsFakePlayer && Player.User != Null) {
BotUserIds.add(Player.User.Id);
}
}
// Set number of bots
declare NbPlayers = Players.count - BotUserIds.count;
if (NbPlayers <= 0) {
Users_DestroyAllFakes();
Users_SetNbFakeUsers(0, 0);
} else {
declare NbBots = S_AddinBots-NbPlayers;
if (NbBots < 0) {
NbBots = 0;
} else if (NbBots > 25) {
NbBots = 25;
UIManager.UIAll.SendChat("""$s$f80Overload Ban, Reset Bot Count to $ccc"25" $f20$w!""");
}
//declare Temp = Users_CreateFake("Hylis", 0);
Users_SetNbFakeUsers(NbBots, 0);
}
// Reset scores of disconnected bots
foreach (Score in Scores) {
if (Score.User != Null && Score.User.IsFakeUser && !BotUserIds.exists(Score.User.Id)) {
Score.Clear();
}
}
}
// Check setting updates
Void CheckSettings() {
// Specialized Mode Settings
declare OldMode for This = S_Mode;
if (OldMode != S_Mode) {
SM::UnspawnAllPlayers();
OldMode = S_Mode;
declare ModeName = "";
switch (S_Mode) {
case 1:
{
foreach(Player, Players) {
ModeName = "$03fDefault $dddMode is activated";
SetPlayerAmmoMax(Player, CSmMode::EWeapon::Laser, 1);
SetPlayerAmmoMax(Player, CSmMode::EWeapon::Rocket, 4);
SetPlayerAmmoMax(Player, CSmMode::EWeapon::Arrow, 3);
SetPlayerAmmoMax(Player, CSmMode::EWeapon::Nucleus, 3);
SetPlayerWeapon(Player, CSmMode::EWeapon::Rocket, True);
Player.ForceColor = <0.0, 0.0, 0.1>;
Player.StaminaMax = 3.0;
Player.AmmoPower = 1.5;
Player.AmmoGain = 1.75;
Player.ArmorMax = 400;
Player.ArmorGain = 3;
Player.Armor = 300;
//S_PointLimit = 45;
//Player.StaminaGain = 4.0;
//SetWeaponRefire(Player, CSmMode::EWeapon::Nucleus, 5.0??);
}
}
case 2:
{
foreach(Player, Players) {
ModeName = "$ff0InstaShot $dddMode is activated";
SetPlayerAmmoMax(Player, CSmMode::EWeapon::Rocket, 1);
SetPlayerAmmoMax(Player, CSmMode::EWeapon::Laser, 1);
SetPlayerAmmoMax(Player, CSmMode::EWeapon::Arrow, 1);
SetPlayerAmmoMax(Player, CSmMode::EWeapon::Nucleus, 1);
Player.ForceColor = <0.5, 0.5, 0.0>;
Player.IsHighlighted = True;
Player.StaminaMax = 2.0;
Player.AmmoGain = 2.0;
Player.ArmorMax = 100;
Player.Armor = 100;
}
}
case 3:
{
foreach(Player, Players) {
ModeName = "$0f0UltraSkeet $dddMode is activated";
SetPlayerAmmoMax(Player, CSmMode::EWeapon::Rocket, 1);
SetPlayerAmmoMax(Player, CSmMode::EWeapon::Laser, 1);
SetPlayerAmmoMax(Player, CSmMode::EWeapon::Arrow, 1);
SetPlayerAmmoMax(Player, CSmMode::EWeapon::Nucleus, 1);
Player.ForceColor = <0., .5, 0.>;
Player.StaminaMax = 3.0;
Player.AmmoPower = 1.0;
Player.AmmoGain = 7.0;
Player.ArmorMax = 800;
Player.ArmorGain = 7;
Player.Armor = 800;
}
}
}
if (S_Mode != 0) {
UIManager.UIAll.SendChat("""{{{ModeName}}} $f20$w!""");
}
}
// Weapon Settings
declare OldWeaponNumber for This = S_WeaponNumber;
if (OldWeaponNumber != S_WeaponNumber) {
OldWeaponNumber = S_WeaponNumber;
declare WeaponName = "";
switch (S_WeaponNumber) {
case 1: {
WeaponName = "$f90Rockets";
}
case 2: {
WeaponName = "$0f0Lasers";
}
case 3: {
WeaponName = "$03fNucleus";
}
case 4: {
WeaponName = "$f20Arrows";
}
}
if (WeaponName != "") {
SM::UnspawnAllPlayers();
UIManager.UIAll.SendChat("""$dddSpawning with {{{WeaponName}}} $f20$w!""");
}
}
// Update UI points limit
declare LastPointsLimit for This = S_PointsLimit;
if (LastPointsLimit != S_PointsLimit) {
LastPointsLimit = S_PointsLimit;
SetFooterStats(Null);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment