Page 1 of 2

ManiaScript

Posted: 17 Apr 2014, 06:22
by SmokyBird
Bon...

Je viens de passer une nuit entière à essayer de créer un premier script pour ShootMania. Et le résultat : ça me gonfle d'une force, pour une raison précise, AUCUN tutoriel n'existe afin de savoir comment en créer un.

Alors oui, j'ai déjà été vérifié sur le net et sur le forum, tout ce que je trouve, c'est juste la documentation et un bout de code qui ne permet jusque que de "démarrer" le script sur le serveur. Rien de plus.

Voilà où j'en suis pour le moment :

Code: Select all

while ( !ServerShutdownRequested )
{
    // Règles du jeu
    declare RulesTitle = "Battlefield";
    declare RulesText = TextLib::Compose(_("Ceci est un exemple !"));
	
    Rules::Create(RulesTitle, RulesText);
	
    yield;
}
Après, je ne sais strictement plus rien faire.
Partout où j'ai cherché, il est écrit nul part comment récupérer la liste des joueurs présents sur le serveur, comment les faire spawner, etc.

Et c'est un peu gavant pour quelqu'un comme moi qui fait de la programmation web depuis désormais 4 ans.

Du coup, si quelqu'un peut m'aider afin de mieux comprendre comment créer un script, je lui en serais énormément reconnaissant.

Re: ManiaScript

Posted: 17 Apr 2014, 08:08
by Hylis
Regarder les script existants reste encore la meilleure manière aujourd'hui. Nous avons l'ambitions d'améliorer l'aide à ce niveau, et depuis longtemps, et même plus que de puis ton post.

Si tu regardes le code de Melee, il a quelques commentaires qui peuvent aider aussi. Je ne sais pas si ça apporte un petit plus, ou si c'est dans ce sens que tu cherches des infos, et je pense que tu les as déjà, mais c'est tout ce à quoi je pense pour l'instant.

Code: Select all

/**
 *	Mode melee
 */

#Extends "Modes/ShootMania/ModeBase.Script.txt"

#Const	CompatibleMapTypes	"MeleeArena"
#Const	Version				"2013-12-13"
#Const	ScriptName			"Melee.Script.txt"

#Include "MathLib" as MathLib
#Include "TextLib" as TextLib
#Include "Libs/Nadeo/Message.Script.txt" as Message
#Include "Libs/Nadeo/Interface.Script.txt" as Interface
#Include "Libs/Nadeo/ShootMania/SM.Script.txt" as SM
#Include "Libs/Nadeo/ShootMania/Score.Script.txt" as Score
#Include "Libs/Nadeo/ShootMania/SpawnScreen.Script.txt" as SpawnScreen

// ---------------------------------- //
// Settings
// ---------------------------------- //
#Setting S_TimeLimit	600 as _("Time limit")		///< Time limit on a map
#Setting S_PointLimit	25	as _("Points limit")	///< Points limit on a map

#Const C_NbBots			0	///< Number of bots

#Const Description _("TYPE: Free for all\nOBJECTIVE: Hit your opponents to score points. The first player to reach the points limit or the player with the highest score at the end of the time limit wins the map.")

// ---------------------------------- //
// Globales variables
// ---------------------------------- //
declare Ident[]	G_SpawnsList;		///< Id of all the landmarks with a player spawn of the map
declare Ident	G_LatestSpawnId;	///< Id of the last landmark used

// ---------------------------------- //
// Extend
// ---------------------------------- //

***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(SpawnScreen::GetScriptName(), SpawnScreen::GetScriptVersion());
***

// ---------------------------------- //
// Set rules
// ---------------------------------- //
***Rules***
***
declare ModeName = "Melee";
declare ModeRules = TextLib::Compose(_("$<%11. $>Hit your opponents to score points.\n$<%12. $>The first player to reach the points limit or the player with the highest score at the end of the time limit wins the map."), "$"^SpawnScreen::GetModeColor());
SpawnScreen::AddSubsection(_("Type"), _("Free for all"), 0.);
SpawnScreen::AddSubsection(_("Objectives"), ModeRules, 20.);
SpawnScreen::CreatePrettyRules(ModeName);
ModeStatusMessage = _("TYPE: Free for all\nOBJECTIVE: Hit a maximum of players to win the game.");
***

// ---------------------------------- //
// Server start
// ---------------------------------- //
***StartServer***
***
// ---------------------------------- //
// Set mode options
UseClans = False;

// ---------------------------------- //
// Create the rules
---Rules---

// ---------------------------------- //
// Initialize UI
SpawnScreen::CreateScores("Score.RoundPoints");
SpawnScreen::CreateMapInfo();
Interface::CreateRank();

// ---------------------------------- //
// Create the scores table
ST2::SetStyle("LibST_SMBaseSolo");
ST2::SetStyle("LibST_SMBasePoints");
MB_SetScoresTableStyleFromXml(S_ScoresTableStylePath);
ST2::Build("SM");
***

***InitMap***
***
declare PrevPointsLimit = -1;
***

// ---------------------------------- //
// Map start
// ---------------------------------- //
***StartMap***
***
Users_SetNbFakeUsers(C_NbBots, 0);
G_SpawnsList.clear();
G_LatestSpawnId = NullId;
Score::MatchBegin();
Score::RoundBegin();

SM::SetupDefaultVisibility();

// ---------------------------------- //
// Init bases
foreach (Base in MapBases) {
	Base.Clan = 0;
	Base.IsActive = True;
}

// ---------------------------------- //
// Init scores
MB_Sleep(1); ///< Allow the scores array to be sorted
foreach (Score in Scores) {
	declare Integer LastPoint for Score;
	LastPoint = 0;
}
declare LeadId = NullId;
if (Scores.existskey(0)) LeadId = Scores[0].User.Id;

// ---------------------------------- //
// New map sound
UIManager.UIAll.SendNotice("", CUIConfig::ENoticeLevel::MatchInfo, Null, CUIConfig::EAvatarVariant::Default, CUIConfig::EUISound::StartRound, 0);

StartTime = Now;
if (S_TimeLimit > 0) EndTime = StartTime + (S_TimeLimit * 1000);
else EndTime = -1;
UIManager.UIAll.UISequence = CUIConfig::EUISequence::Playing;
declare CurrentTimeLimit = S_TimeLimit;
***

// ---------------------------------- //
// Play loop
// ---------------------------------- //
***PlayLoop***
***
foreach (Event, PendingEvents) {
	// ---------------------------------- //
	// On armor empty
	if (Event.Type == CSmModeEvent::EType::OnArmorEmpty) {
		if (Event.Shooter == Event.Victim || Event.Shooter == Null) {
			Score::RemovePoints(Event.Victim, 1);
		}
		XmlRpc::OnArmorEmpty(Event);
		PassOn(Event);
	} 
	// ---------------------------------- //
	// On hit
	else if (Event.Type == CSmModeEvent::EType::OnHit) {
		if (Event.Victim == Null || Event.Shooter == Event.Victim) {
			Discard(Event);
		} else {
			declare Points = Event.Damage / 100;
			Score::AddPoints(Event.Shooter, Points);
			Event.ShooterPoints = Points;
			
			// ---------------------------------- //
			// 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_PointLimit - Event.Shooter.Score.RoundPoints;
				if (Gap > 0 && Gap <= 3) {
					declare Variant = 3 - Gap;
					declare Msg = "";
					if (Gap > 1) Msg = TextLib::Compose(_("$<%1$> is %2 points from victory!"), Event.Shooter.Name, TextLib::ToText(Gap));
					else Msg = TextLib::Compose(_("$<%1$> is 1 point from victory!"), Event.Shooter.Name);
					Message::SendBigMessage(Msg, 3000, 2, CUIConfig::EUISound::TieBreakPoint, Variant);
				} else if (Gap <= 0) {
					Message::SendBigMessage(
						TextLib::Compose(_("$<%1$> gets the final hit!"), Event.Shooter.Name),
						3000, 3, CUIConfig::EUISound::VictoryPoint, 0
					);
				} else {
					declare SoundGap = S_PointLimit / 5;
					if (SoundGap < 5) SoundGap = 5;
					if (Event.Shooter.Score.RoundPoints / SoundGap > LastPoint) {
						LastPoint = Event.Shooter.Score.RoundPoints / SoundGap;
						declare Msg = TextLib::Compose(
							"$666%1 : $fff%2 / %3", _("Score"), TextLib::ToText(Event.Shooter.Score.RoundPoints), TextLib::ToText(S_PointLimit)
						);
						declare Variant = ((Event.Shooter.Score.RoundPoints / SoundGap) - 1);
						Message::SendBigMessage(Event.Shooter, Msg, 3000, 0, CUIConfig::EUISound::ScoreProgress, Variant);
					}
				}
			}
			XmlRpc::OnHit(Event);
			PassOn(Event);
		}
	} 
	// ---------------------------------- //
	// On player request respawn
	else if (Event.Type == CSmModeEvent::EType::OnPlayerRequestRespawn) {
		Score::RemovePoints(Event.Player, 1);
		XmlRpc::OnPlayerRequestRespawn(Event);
		PassOn(Event);
	} 
	// ---------------------------------- //
	// Others
	else {
		PassOn(Event);
	}
}	

// ---------------------------------- //
// Spawn players
foreach (Player in Players) {
	if (Player.SpawnStatus == CSmPlayer::ESpawnStatus::NotSpawned && !Player.RequestsSpectate) {
		MeleeSpawnPlayer(Player);
	}
}

// ---------------------------------- //
// Play sound and notice if someone is taking the lead
if (Scores.existskey(0) && Scores[0].User.Id != LeadId) {
	LeadId = Scores[0].User.Id;
	Message::SendBigMessage(TextLib::Compose(_("$<%1$> takes the lead!"), Scores[0].User.Name), 3000, 1, CUIConfig::EUISound::PhaseChange, 1);
}

// ---------------------------------- //
// Server info change
if (PrevPointsLimit != S_PointLimit) {
	PrevPointsLimit = S_PointLimit;
	ST2::SetFooterText(TextLib::Compose("%1 "^S_PointLimit, _("Points limit : ")));
}

// ---------------------------------- //
// 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
declare IsMatchOver = False;
if (S_TimeLimit > 0 && Now > EndTime) IsMatchOver = True;
if (S_PointLimit > 0) {
	foreach (Player in Players) {
		if (Player.Score != Null && Player.Score.RoundPoints >= S_PointLimit) IsMatchOver = True;
	}
}

if (IsMatchOver) MB_StopMap = True;
***

// ---------------------------------- //
// Map end
// ---------------------------------- //
***EndMap***
***
EndTime = -1;
Score::RoundEnd();
Score::MatchEnd(True);

// ---------------------------------- //
// End match sequence
declare CUser Winner <=> Null;
declare MaxPoints = 0;
foreach (Score in Scores) {
	if (Score.Points > MaxPoints) {
		MaxPoints = Score.Points;
		Winner <=> Score.User;
	} else if (Score.Points == MaxPoints) {
		Winner <=> Null;
	}
}
foreach (Player in Players) {
	if (Player.User != Winner) UnspawnPlayer(Player);
}

MB_Sleep(1000);
Message::CleanBigMessages();
UIManager.UIAll.BigMessageSound = CUIConfig::EUISound::EndRound;
UIManager.UIAll.BigMessageSoundVariant = 0;
if (Winner != Null) {
	UIManager.UIAll.BigMessage = TextLib::Compose(_("$<%1$> wins the match!"), Winner.Name);
} else {
	UIManager.UIAll.BigMessage = _("|Match|Draw");
}
MB_Sleep(2000);
UIManager.UIAll.UISequence = CUIConfig::EUISequence::EndRound;
UIManager.UIAll.ScoreTableVisibility = CUIConfig::EVisibility::ForcedVisible;
MB_Sleep(5000);

UIManager.UIAll.UISequence = CUIConfig::EUISequence::Podium;
while(!UIManager.UIAll.UISequenceIsCompleted) {
	MB_Yield();
}

UIManager.UIAll.ScoreTableVisibility = CUIConfig::EVisibility::Normal;
UIManager.UIAll.BigMessage = "";
***

// ---------------------------------- //
// Server end
// ---------------------------------- //
***EndServer***
***
Interface::DestroyRank();
SpawnScreen::DestroyRules();
SpawnScreen::DestroyScores();
SpawnScreen::DestroyMapInfo();
***

// ---------------------------------- //
// Functions
// ---------------------------------- //

/* ------------------------------------- */
/** Spawn a player
 *
 * @param	_Player		The player to spawn
 */
Void MeleeSpawnPlayer(CSmPlayer _Player) {
	if (G_SpawnsList.count == 0) {
		foreach (MapLandmark in MapLandmarks_PlayerSpawn) G_SpawnsList.add(MapLandmark.Id);
	}
	
	declare SpawnId = NullId;
	while (True) {
		SpawnId = G_SpawnsList[MathLib::Rand(0, G_SpawnsList.count - 1)];
		if (SpawnId != G_LatestSpawnId) break;
		if (G_SpawnsList.count == 1) break;
	}
	G_LatestSpawnId = SpawnId;
	SM::SpawnPlayer(_Player, 0, MapLandmarks_PlayerSpawn[SpawnId].PlayerSpawn);
	declare Removed = G_SpawnsList.remove(SpawnId);
}

Re: ManiaScript

Posted: 17 Apr 2014, 10:58
by Cerovan
SmokyBird wrote:Bon...

Je viens de passer une nuit entière à essayer de créer un premier script pour ShootMania. Et le résultat : ça me gonfle d'une force, pour une raison précise, AUCUN tutoriel n'existe afin de savoir comment en créer un.
Je suis en train d'écrire un tutoriel (en anglais par contre) qui devrait être disponible à la release de MP3 :thumbsup:

Re: ManiaScript

Posted: 17 Apr 2014, 11:30
by steeffeen
Salut

If you're able to understand English then my blog might help you.
(A friend also created French versions of some of the posts.)

http://blog.steeffeen.com

Sorry for the English, even though I understand some French I'm terrible at writing in French. ;)

Re: ManiaScript

Posted: 17 Apr 2014, 11:45
by Hylis
Cerovan wrote:
SmokyBird wrote:Bon...

Je viens de passer une nuit entière à essayer de créer un premier script pour ShootMania. Et le résultat : ça me gonfle d'une force, pour une raison précise, AUCUN tutoriel n'existe afin de savoir comment en créer un.
Je suis en train d'écrire un tutoriel (en anglais par contre) qui devrait être disponible à la release de MP3 :thumbsup:
bwwwwwaaaa, il pourrait le traduire après :mrgreen:

Re: ManiaScript

Posted: 17 Apr 2014, 12:22
by spaii
Hylis wrote:bwwwwwaaaa, il pourrait le traduire après :mrgreen:
:roflol:

Re: ManiaScript

Posted: 17 Apr 2014, 12:34
by SmokyBird
Hylis wrote:
Cerovan wrote:
SmokyBird wrote:Bon...

Je viens de passer une nuit entière à essayer de créer un premier script pour ShootMania. Et le résultat : ça me gonfle d'une force, pour une raison précise, AUCUN tutoriel n'existe afin de savoir comment en créer un.
Je suis en train d'écrire un tutoriel (en anglais par contre) qui devrait être disponible à la release de MP3 :thumbsup:
bwwwwwaaaa, il pourrait le traduire après :mrgreen:
Le pire, c'est que j'en serais capable ^^ Vu que j'avais dit que je ferais un tutoriel une fois que j'aurais réussi à créer un script.

J'avais déjà été voir des exemples de codes sur d'autres scripts, mais faut reconnaître qu'il y a des bouts de codes que des fois, c'est un peu incompréhensible. Si encore, les fonctions restaient dans le script même, passe encore. Mais s'il faut chercher dans les plusieurs fichiers inclus, c'est un peu hardcore de vouloir chercher la fonction enfouie parmi 2.000 lignes de codes :|

Enfin, merci quand même pour les infos. Je décourage pas, j'ai déjà connu pire au niveau de la programmation (comme par exemple en faire sur un vieux micro-processeur Motorola 6800, pour ceux qui savent de quoi je parle)

Re: ManiaScript

Posted: 17 Apr 2014, 18:03
by The_Big_Boo
SmokyBird wrote:j'ai déjà connu pire au niveau de la programmation (comme par exemple en faire sur un vieux micro-processeur Motorola 6800, pour ceux qui savent de quoi je parle)
Je désapprouve, j'avais trouvé ça fun les cours d'assembleur (c'est le bonheur quand après quelques heures t'arrives enfin à allumer quelques pauvres LED qui simulent un carrefour avec feux tricolores :roflol: )

Re: ManiaScript

Posted: 17 Apr 2014, 19:35
by Slig
Je désapprouve, j'avais trouvé ça fun les cours d'assembleur (c'est le bonheur quand après quelques heures t'arrives enfin à allumer quelques pauvres LED qui simulent un carrefour avec feux tricolores :roflol: )
Tu aurais surement aimé les micro-ordis du milieu des années 80, où tu faisais des petits jeux en basic... ou en assembleur :D Bon c'était pas le même genre de jeux ;)
Enfin le top c'était les 680x0, un vrai plaisir l'assembleur dessus, pas comme sur x86...

Re: ManiaScript

Posted: 17 Apr 2014, 19:58
by The_Big_Boo
C'est l'inconvénient d'être jeune :P Cela dit j'ai failli récupérer un Amstrad CPC (potentiellement encore en état de marche) il y a pas longtemps via la famille de ma copine mais il a disparu et personne ne sait si quelqu'un d'autre l'a déjà récupéré ou s'il a carrément été balancé :(