De/Creating A Class System: Difference between revisions
m (→Einleitung) |
mNo edit summary |
||
(11 intermediate revisions by 7 users not shown) | |||
Line 1: | Line 1: | ||
{{ | {{LanguageBar|title=Erstellen eines Klassensystems}} | ||
{{ | {{Pov}} | ||
{{Toc-right}} | |||
==Einleitung== | ==Einleitung== | ||
Dieses Coding Tutorial befasst sich mit dem Erstellen eines Klassensystems. | Dieses Coding Tutorial befasst sich mit dem Erstellen eines Klassensystems. | ||
Notizen (/Überlegungen): | Notizen (/Überlegungen): | ||
*Es | *Es gibt 3 Klassen (Supporter, Medic und Assaulter) | ||
*Beim ersten Spawn bekommt man eine Standardklasse. | *Beim ersten Spawn bekommt man eine Standardklasse. | ||
*Wechselt man die Klasse, stirbt man und | *Wechselt man die Klasse, stirbt man und spawnt mit der neuen Klasse. | ||
==Daten die gebraucht werden== | ==Daten, die gebraucht werden== | ||
Als erstes eine Auflistung was | Als erstes eine Auflistung was man an Codedateien braucht: | ||
Header: | Header: | ||
Line 19: | Line 21: | ||
Das Klassensystem wird zu 100% | Das Klassensystem wird zu 100% serverseitig sein, der Client kann die Klassen aber wechseln. | ||
==Die Deklarationen== | ==Die Deklarationen== | ||
Als erstes | Als erstes muss man die Deklarationen machen. | ||
Was | Was man braucht sind einige Variablen und einige Funktionen. | ||
Als Erstes erstellt man ein Enum das die Werte der Klassen enthält! | |||
Das enum kommt in die ''player.h'' über ''class CBasePlayer;'' | Das enum kommt in die ''player.h'' über ''class CBasePlayer;'' | ||
Das Enum | Das Enum macht man erstmal so: | ||
enum | enum | ||
{ | { | ||
Line 37: | Line 39: | ||
}; | }; | ||
Später | Später braucht man das für die Vergleiche! | ||
Jetzt | Jetzt widme man sich der Klasse ''CBasePlayer''. | ||
Zum Beginn | Zum Beginn erstellt man einen neuen ''public'' und einen neuen ''private'' Bereich am Ende von ''CBasePlayer'' in der ''player.h''. | ||
Dort | Dort schreibt man den gesamten Code für das Klassensystem rein! | ||
// Die neuen Bereiche für das Klassensystem! | // Die neuen Bereiche für das Klassensystem! | ||
Line 49: | Line 51: | ||
Hier nun alles was | Hier nun alles was man an Methoden deklarieren muss und natürlich auch die Variablen: | ||
/* | /* | ||
Line 123: | Line 125: | ||
int m_iMaxArmor; | int m_iMaxArmor; | ||
Nun | Nun zur Erklärung, von oben nach unten. | ||
==public== | ==public== | ||
Line 131: | Line 132: | ||
virtual void ChangeClass(int NewClass); | virtual void ChangeClass(int NewClass); | ||
Diese Methode | Diese Methode braucht man, damit der Client(Spieler) per Menu/Konsole seine Klasse wechselt. | ||
virtual int GetClass(); | virtual int GetClass(); | ||
Braucht man, wenn man noch Sachen wie Munition, Leben und Rüstungsinkrementierung für den Supporter/Medic einbauen will. | |||
// Initalisierung des Klassensystems! | // Initalisierung des Klassensystems! | ||
Line 142: | Line 143: | ||
Diese Methode soll das Klassensystem aus der Spawn Methode von CBasePlayer starten. | Diese Methode soll das Klassensystem aus der Spawn Methode von CBasePlayer starten. | ||
Damit werden die Methoden für die Klassenverteilung usw aufgerufen. | Damit werden die Methoden für die Klassenverteilung usw aufgerufen. | ||
Bei der Implementierung | Bei der Implementierung ist man dann schlauer. | ||
// Überprüft ob | // Überprüft ob man keinen ungültigen wert setzt für die Klassenvariablen: | ||
void CheckAllClassConVars(); | void CheckAllClassConVars(); | ||
Diese Methode prüft ob | Diese Methode prüft, ob man einen gültigen Wert eingegeben hat. | ||
Falls wir das nicht Prüfen würden dann würde eure Mod crashen | Falls wir das nicht Prüfen würden, dann würde eure Mod crashen! | ||
Falls der Wert nicht | Falls der Wert nicht stimmt, dann müsst ihr einen Wert für die Klasse setzen. | ||
// Hier wird geprüft ob | // Hier wird geprüft ob man die Klasse gewechselt hat: | ||
void OnClassChange(); | void OnClassChange(); | ||
Diese Methode wird in der Thinkmethode gebraucht. | Diese Methode wird in der Thinkmethode gebraucht. | ||
Falls | Falls man die Klasse wechselt wird man gekillt und ein Punkt addiert sonst würde man Punktabzug bekommen. | ||
// Setzt Leben und Armor für den Spieler! | // Setzt Leben und Armor für den Spieler! | ||
Line 161: | Line 162: | ||
Diese Methode setzt für jede Klasse den Wert für das Leben, Maximal Leben und Rüstung. | Diese Methode setzt für jede Klasse den Wert für das Leben, Maximal Leben und Rüstung. | ||
Leider wird die Rüstung über den Code der Recharger festgelegt | Leider wird die Rüstung über den Code der Recharger festgelegt, diesen muss man selber ändern. | ||
// Setzt den neuen wert für die Check Variable: | // Setzt den neuen wert für die Check Variable: | ||
void SetCurrentClassValue(); | void SetCurrentClassValue(); | ||
Diese Methode ändert den Wert der CheckVariable für die Klassen sonst würde man immer wieder sterben! | Diese Methode ändert den Wert der CheckVariable für die Klassen, sonst würde man immer wieder sterben! | ||
// Die Klasse holen: | // Die Klasse holen: | ||
int GetClassValue()const; | int GetClassValue()const; | ||
Diese Methode holt | Diese Methode holt den Wert der Klasse die man hat. | ||
// Die Standartklasse holen: | // Die Standartklasse holen: | ||
int GetDefaultClassValue()const; | int GetDefaultClassValue()const; | ||
Diese Methode holt | Diese Methode holt vom Server die Standardklasse damit man im Falle einer ungültigen Klasse diese bekommt. | ||
// Schaltmethode die Klassen verteilt: | // Schaltmethode die Klassen verteilt: | ||
Line 182: | Line 183: | ||
Diese Methode ist die Steuerzentrale unseres Klassensystems. | Diese Methode ist die Steuerzentrale unseres Klassensystems. | ||
Dort wird mit dem Wert der Klassenvariable alles gelenkt. Von der Waffen und Lebensverteilung bis zum setzen des Spielermodels( | Dort wird mit dem Wert der Klassenvariable alles gelenkt. Von der Waffen und Lebensverteilung bis zum setzen des Spielermodels (Das muss man leider noch machen!). | ||
// Legt das Leben für | // Legt das Leben für die Klasse fest: | ||
int GetClassHealth()const; | int GetClassHealth()const; | ||
Diese Methode holt das Leben das | Diese Methode holt das Leben, das man im Moment hat. | ||
// Diese Methoden | // Diese Methoden setzt für jede Klasse das Leben und die Armor | ||
int GetClassMaxHealth()const; | int GetClassMaxHealth()const; | ||
Die Methode holt das Maximale Leben das | Die Methode holt das Maximale Leben, das die Klasse haben kann. | ||
// Legt die Armor für die Klasse Fest: | // Legt die Armor für die Klasse Fest: | ||
int GetClassArmor()const; | int GetClassArmor()const; | ||
Diese Methode holt | Diese Methode holt die Rüstung, die man im Moment hat. | ||
// Diese Methoden | // Diese Methoden holt für jede Klasse das Leben und die Armor | ||
int GetClassMaxArmor()const; | int GetClassMaxArmor()const; | ||
Diese Methode holt die Maximale Rüstung | Diese Methode holt die Maximale Rüstung der Klasse (ist leider noch unbrauchbar wegen dem Recharger Code!) | ||
==private== | ==private== | ||
Line 210: | Line 211: | ||
bool m_bFirstSpawn; | bool m_bFirstSpawn; | ||
Diese Variable ist für die | Diese Variable ist für die Abfrage für den ersten Spawn nötig. | ||
bool IsFirstSpawn(); | bool IsFirstSpawn(); | ||
Diese Methode gibt | Diese Methode gibt Auskunft ob man das Erste mal gespawnt wird. | ||
// Welche Klasse | // Welche Klasse hat man(enum): | ||
int m_iClass; | int m_iClass; | ||
Diese Variable speichert den Wert | Diese Variable speichert den Wert der Klasse: | ||
// Prüft ob | // Prüft, ob man die Klasse gewechselt hat: | ||
int m_iCurrentClass; | int m_iCurrentClass; | ||
Das ist die Prüfungsvariable die den Wert | Das ist die Prüfungsvariable, die den Wert der Momentanen Klasse enthält. | ||
Der Wert wird dann geändert | Der Wert wird dann geändert wenn die Klasse gewechselt wird. | ||
// Hier | // Hier setzt man die Standardklasse! | ||
int m_iDefaultClass; | int m_iDefaultClass; | ||
Diese Variable holt die Klasse des Servers und ist gleichzeitig die erste Klasse die man beim ersten | Diese Variable holt die Klasse des Servers und ist gleichzeitig die erste Klasse, die man beim ersten Spawn | ||
bekommt | bekommt. | ||
// Waffen, Leben und Armor der Klassen verteilen: | // Waffen, Leben und Armor der Klassen verteilen: | ||
Line 238: | Line 239: | ||
void SetClassMedic(); | void SetClassMedic(); | ||
Das sind | Das sind die Methoden zum verteilen aller wichtigen Sachen einer Klasse. | ||
(Leben, Maximalleben, Rüstung, Maximalrüstung, Waffen usw.) | |||
// Integer für Rüstung: | // Integer für Rüstung: | ||
Line 245: | Line 246: | ||
int m_iMaxArmor; | int m_iMaxArmor; | ||
Das sind | Das sind die Variablen für Rüstung und Maximalrüstung. | ||
Jetzt | Jetzt wei0 man was man alles braucht und wieso. | ||
Nun | Nun kommt man zum Teil in dem man alles Einbaut. | ||
==Die Implementation== | ==Die Implementation== | ||
Da | Da man nun alles hat was man braucht muss man nurnoch alles einbauen! | ||
Alles kommt in die ''player.cpp'' ganz ans Ende | Alles kommt in die ''player.cpp'' ganz ans Ende. | ||
Hier der Code mit | Hier der Code mit Erklärung: | ||
Added im Konstruktor: | Added im Konstruktor: | ||
// Erster Spawn? | // Erster Spawn? | ||
m_bFirstSpawn = true; | |||
// Startklasse festlegen: | // Startklasse festlegen: | ||
m_iClass = default_class.GetInt(); | |||
m_iCurrentClass = m_iClass; | |||
// Die | // Die Standardklasse setzen! | ||
m_iDefaultClass = default_class.GetInt(); | |||
// Standartwerte 100 für | // Standartwerte 100 für Leben/Armor: | ||
m_iHealth = 100; | |||
m_iArmor = 100; | |||
// Maximal Leben/Armor für | // Maximal Leben/Armor für jede Klasse: | ||
m_iMaxHealth = 100; | |||
m_iMaxArmor = 100; | |||
void CBasePlayer::InitClassSystem() | void CBasePlayer::InitClassSystem() | ||
Line 308: | Line 309: | ||
m_iClass = m_iDefaultClass; | m_iClass = m_iDefaultClass; | ||
} | } | ||
// Jetzt werden die | // Jetzt werden die Klassen verteilt: | ||
switch(m_iClass) | switch(m_iClass) | ||
{ | { | ||
Line 322: | Line 323: | ||
//case Invalid: | //case Invalid: | ||
// Muss noch eingebaut werden! | // Muss noch eingebaut werden! | ||
// Hier bekommt man nur die | // Hier bekommt man nur die Standardwaffen! | ||
case Unassigned: | case Unassigned: | ||
// Hier | // Hier setzt man die Standardklasse! | ||
default: | default: | ||
SetClassDefault(); | SetClassDefault(); | ||
Line 335: | Line 336: | ||
if( m_iClass != m_iCurrentClass ) | if( m_iClass != m_iCurrentClass ) | ||
{ | { | ||
// Spieler killen und | // Spieler killen und Punkte um 1 erhöhen (wegen Selbstmord)! | ||
CommitSuicide(); | CommitSuicide(); | ||
IncrementFragCount(1); | IncrementFragCount(1); | ||
// Setzen damit | // Setzen, damit man nicht die selbe Klasse hat! | ||
m_iCurrentClass = m_iClass; | m_iCurrentClass = m_iClass; | ||
} | } | ||
Line 346: | Line 347: | ||
void CBasePlayer::CheckAllClassConVars() | void CBasePlayer::CheckAllClassConVars() | ||
{ | { | ||
// | // Hat man eine Klasse, die zwischen Spec-Ops und der letzen Klasse liegt? | ||
if( m_iClass < Assaulter || m_iClass > Medic ) | if( m_iClass < Assaulter || m_iClass > Medic ) | ||
{ | { | ||
Line 369: | Line 370: | ||
void CBasePlayer::SetClassGroundUnit() | void CBasePlayer::SetClassGroundUnit() | ||
{ | { | ||
// | // Standardwerte für Leben/Armor: | ||
m_iHealth = 125; | m_iHealth = 125; | ||
m_iArmor = 125; | m_iArmor = 125; | ||
// Maximal Leben/Armor für | // Maximal Leben/Armor für jede Klasse: | ||
m_iMaxHealth = 125; | m_iMaxHealth = 125; | ||
m_iMaxArmor = 125; | m_iMaxArmor = 125; | ||
Line 420: | Line 421: | ||
void CBasePlayer::SetClassMedic() | void CBasePlayer::SetClassMedic() | ||
{ | { | ||
// | // Standardwerte für Leben/Armor: | ||
m_iHealth = 100; | m_iHealth = 100; | ||
m_iArmor = 75; | m_iArmor = 75; | ||
Line 439: | Line 440: | ||
} | } | ||
// Legt das Leben für | // Legt das Leben für die Klasse fest: | ||
int CBasePlayer::GetClassHealth()const | int CBasePlayer::GetClassHealth()const | ||
{ | { | ||
Line 445: | Line 446: | ||
} | } | ||
// Legt die Armor für die Klasse | // Legt die Armor für die Klasse fest: | ||
int CBasePlayer::GetClassArmor()const | int CBasePlayer::GetClassArmor()const | ||
{ | { | ||
Line 471: | Line 472: | ||
// Variable gehört nicht zu CBasePlayer!!! | // Variable gehört nicht zu CBasePlayer!!! | ||
// TODO: Das ist eine Private Variable die ich ändern muss! | // TODO: Das ist eine Private Variable, die ich ändern muss! | ||
SetArmorValue(GetClassArmor()); | SetArmorValue(GetClassArmor()); | ||
// SetMaxArmorValue(GetClassMaxArmor()); | // SetMaxArmorValue(GetClassMaxArmor()); | ||
} | } | ||
// Klasse per ConVar | // Klasse per ConVar Wechsel für Client: | ||
void CBasePlayer::ChangeClass(int NewClass) | void CBasePlayer::ChangeClass(int NewClass) | ||
{ | { | ||
Line 482: | Line 483: | ||
} | } | ||
Da | Da man ja schon weiß, wofür die ganzen Methoden sind, man nurnoch schauen wie alles läuft :) | ||
Aber nun mal zum | Aber nun mal zum Einbauen der ConVars, die man braucht: | ||
// Der Server hat für alle die selbe | // Der Server hat für alle die selbe Standardklasse! | ||
// Der Admin kann die Standartklasse ändern! | // Der Admin kann die Standartklasse ändern! | ||
ConVar default_class("default_class", "3", FCVAR_ARCHIVE, "Variable für | ConVar default_class("default_class", "3", FCVAR_ARCHIVE, "Variable für Standardklasse!"); | ||
Nun hat der Server seine Default Klasse die jeder Spieler beim | Nun hat der Server seine Default-Klasse, die jeder Spieler beim Spawnen bekommt. | ||
Diese | Diese kann man dann über die Konsole ändern :) | ||
Man kann auch noch mehr Settings für den Admin zur Verfügung stellen: | |||
// Maximale Klassen erlauben(Admins!) | // Maximale Klassen erlauben(Admins!) | ||
Line 507: | Line 508: | ||
ConVar allow_medic("allow_medic", "1", FCVAR_ARCHIVE, "Erlaubt Klasse Medic!"); | ConVar allow_medic("allow_medic", "1", FCVAR_ARCHIVE, "Erlaubt Klasse Medic!"); | ||
Diese | Diese muss man aber selbst implementieren! | ||
Nun | Nun muss man nur noch dem Spieler die Möglichkeit zum Ändern der Klasse geben! | ||
Und dann muss man noch die Prüfungen der Klassen einbauen! | Und dann muss man noch die Prüfungen der Klassen einbauen! | ||
Dazu | Dazu muss man einfach in der Methode OnClientCommand folgendes am Ende einbauen: | ||
else if ( !stricmp( cmd, "class" ) ) | else if ( !stricmp( cmd, "class" ) ) | ||
Line 525: | Line 526: | ||
} | } | ||
Hiermit wird eine ConVar simuliert. | |||
Aber man kann durch Class und dann die Klassennummer also Class 1 die Klasse ändern! | Aber man kann durch Class und dann die Klassennummer, also Class 1, die Klasse ändern! | ||
Nun | Nun muss man aber die Prüfungsmethode aufrufen und dann hat man es schon! | ||
Das | Das macht man in der Methode PostThink(); | ||
Dort | Dort setzt man am Ende einfach folgendes ein: | ||
OnClassChange(); | OnClassChange(); | ||
Das wars :) wenn alles stimmt dann dürfte | Das wars :) wenn alles stimmt dann dürfte das Klassensystem funktionieren ;) | ||
==Wichtiges zum Code== | ==Wichtiges zum Code== | ||
Damit der Code ohne Probleme läuft | Damit der Code ohne Probleme läuft, muss man noch einiges fixen! | ||
Erstmal | Erstmal muss man noch folgende Methoden im Public-bereich hinzufügen: | ||
// Deklarationen: | // Deklarationen: | ||
Line 587: | Line 588: | ||
} | } | ||
Damit | Damit kann man die Armor und das Health setzen (je nachdem, wieviel die Klassen haben sollen). | ||
Aber auch Medic und Supporter können so ihr Leben/Rüstung regenerieren! | Aber auch Medic und Supporter können so ihr Leben/Rüstung regenerieren! | ||
Line 597: | Line 598: | ||
Die Magazinsdefinitionen: | Die Magazinsdefinitionen: | ||
// Nur verändern wenn man die Munition der Waffenmagazine im script/code ändert! | // Nur verändern, wenn man die Munition der Waffenmagazine im script/code ändert! | ||
// Legt die Magazine fest(Magazin und dann größe in Kugeln)! | // Legt die Magazine fest(Magazin und dann größe in Kugeln)! | ||
#define Magazin_None 0 | #define Magazin_None 0 | ||
Line 630: | Line 631: | ||
#endif //_Magazin_H | #endif //_Magazin_H | ||
Ich würde | Ich würde zur zweiten Methode raten, da man hier auch die Munitionsdefinitions in den gamerules.cpp ändern kann und die maximale Munition einbinden kann! | ||
Und man sollte die Default Klasse per CooVars setzen oder die Default Klasse aus dem Coden komplett entfernen! | Und man sollte die Default Klasse per CooVars setzen oder die Default Klasse aus dem Coden komplett entfernen! | ||
Line 638: | Line 639: | ||
==Klassenmenu öffnen== | ==Klassenmenu öffnen== | ||
Damit man das Klassen system später aufrufen kann solte man in der baseviewport.cpp | Damit man das Klassen system später aufrufen kann, solte man in der baseviewport.cpp dieses eintragen: | ||
dieses eintragen: | |||
// sub dialogs | // sub dialogs | ||
Line 652: | Line 652: | ||
#include "NavProgress.h" | #include "NavProgress.h" | ||
Jetzt den Befehl zum Aufrufen: | |||
CON_COMMAND( chooseclass, "Opens a menu for class choose" ) | CON_COMMAND( chooseclass, "Opens a menu for class choose" ) | ||
Line 662: | Line 662: | ||
} | } | ||
Etwas weiter unten das hier: | |||
void CBaseViewport::CreateDefaultPanels( void ) | void CBaseViewport::CreateDefaultPanels( void ) | ||
Line 680: | Line 680: | ||
} | } | ||
Und zuletzt das hier: | |||
IViewPortPanel* CBaseViewport::CreatePanelByName(const char *szPanelName) | IViewPortPanel* CBaseViewport::CreatePanelByName(const char *szPanelName) | ||
Line 698: | Line 698: | ||
==Bonus== | ==Bonus== | ||
Nun | Nun kann man sich noch einen Spaß erlauben und jeder Klasse eine bestimmte Geschwindigkeit zuweisen. | ||
Dazu | Dazu braucht man die hl2_player.cpp und die player.h/.cpp | ||
Als erstes | Als erstes muss man ausfindig machen, wo der Spieler seine Laufgeschwindigkeit einstellt! | ||
Das macht man hier: | Das macht man hier: | ||
Line 717: | Line 717: | ||
#endif | #endif | ||
Die | Die Erklärung ist simpel. | ||
Wenn HL2MP definiert ist dann werden | Wenn HL2MP definiert ist, dann werden Standardwerte gesetzt: | ||
#ifdef HL2MP | #ifdef HL2MP | ||
Line 725: | Line 725: | ||
#define HL2_SPRINT_SPEED 320 | #define HL2_SPRINT_SPEED 320 | ||
Ansonsten kann man alles über die ConVars machen, aber in HL2DM geht das nur über die Standardwerte! | |||
#else | #else | ||
Line 733: | Line 733: | ||
#endif | #endif | ||
Aber nun | Aber nun muss man eine Steuerung bauen für den Speed! | ||
Dazu | Dazu muss man nur eine Kleinigkeit zum Basisspieler hinzufügen. | ||
player.h öffnen und folgendes im letzten Public-bereich hinzufügen: | |||
// Hier wird die Spielergeschwindigkeit gesetzt: | // Hier wird die Spielergeschwindigkeit gesetzt: | ||
Line 743: | Line 743: | ||
void SetSprintSpeed(int SprintSpeed); | void SetSprintSpeed(int SprintSpeed); | ||
Damit | Damit kann man die Werte setzen, aber nun braucht man noch die Variablen der Klasse: | ||
// Spielergeschwindigkeit: | // Spielergeschwindigkeit: | ||
Line 756: | Line 756: | ||
int GetSprintSpeed(); | int GetSprintSpeed(); | ||
Jetzt | Jetzt zur Implementierung: | ||
void CBasePlayer::SetWalkSpeed(int WalkSpeed) | void CBasePlayer::SetWalkSpeed(int WalkSpeed) | ||
Line 788: | Line 788: | ||
} | } | ||
Jetzt | Jetzt muss man nur noch 2 Sachen tun! | ||
Als erstes | Als erstes muss man sagen, dass die Get Methoden die Geschwindigkeit steuern. | ||
Das | Das macht man wie folgt: | ||
#define HL2_WALK_SPEED CBasePlayer::GetWalkSpeed() | #define HL2_WALK_SPEED CBasePlayer::GetWalkSpeed() | ||
Line 798: | Line 798: | ||
#define HL2_SPRINT_SPEED CBasePlayer::GetSprintSpeed() | #define HL2_SPRINT_SPEED CBasePlayer::GetSprintSpeed() | ||
Das | Das wars auch schon fast. | ||
Jetzt | Jetzt muss man nurnoch definieren welche Geschwindigkeit eure Klasse haben soll. | ||
Dazu | Dazu mmuss man nur in den SetClass Methoden die neuen SetSpeed Methoden einbauen. | ||
Dann | Dann kann man eine Klasse schnell einbauen. | ||
Hier mal ein Beispiel meiner | Hier mal ein Beispiel meiner Supportunit-Klasse: | ||
<code cpp n> | <code cpp n> | ||
// Supporter | // Supporter | ||
Line 855: | Line 855: | ||
} | } | ||
</code> | </code> | ||
Ich habe auch schon die Waffenverteilung auf die Teams gesetzt aber das kann ich auch noch erklären ;) | Ich habe auch schon die Waffenverteilung auf die Teams gesetzt aber das kann ich auch noch erklären ;) Sobald ich das verbessert hab (z.b. mit einer Team-Variable) ;) | ||
Also viel Spaß und schreibt mir falls es Probleme oder Kritik gibt ;) | Also viel Spaß und schreibt mir falls es Probleme oder Kritik gibt ;) | ||
{{ACategory|Programming}}{{ACategory|Tutorials}} |
Latest revision as of 15:29, 14 January 2025

Einleitung
Dieses Coding Tutorial befasst sich mit dem Erstellen eines Klassensystems.
Notizen (/Überlegungen):
- Es gibt 3 Klassen (Supporter, Medic und Assaulter)
- Beim ersten Spawn bekommt man eine Standardklasse.
- Wechselt man die Klasse, stirbt man und spawnt mit der neuen Klasse.
Daten, die gebraucht werden
Als erstes eine Auflistung was man an Codedateien braucht:
Header:
dlls/player.h
Quellcodedateien
dlls/player.cpp
Das Klassensystem wird zu 100% serverseitig sein, der Client kann die Klassen aber wechseln.
Die Deklarationen
Als erstes muss man die Deklarationen machen. Was man braucht sind einige Variablen und einige Funktionen. Als Erstes erstellt man ein Enum das die Werte der Klassen enthält! Das enum kommt in die player.h über class CBasePlayer;
Das Enum macht man erstmal so:
enum { Unassigned = 0, Assaulter, Supporter, Medic, };
Später braucht man das für die Vergleiche!
Jetzt widme man sich der Klasse CBasePlayer.
Zum Beginn erstellt man einen neuen public und einen neuen private Bereich am Ende von CBasePlayer in der player.h. Dort schreibt man den gesamten Code für das Klassensystem rein!
// Die neuen Bereiche für das Klassensystem! public: private:
Hier nun alles was man an Methoden deklarieren muss und natürlich auch die Variablen:
/* ******************************************** **Klassensystem: **Hier werden die Klassen verteilt! **Es wird auch auf die richtigen Klassen geprüft! ******************************************** */ public: // Methode zum Klassenwechseln virtual void ChangeClass(int NewClass); virtual int GetClass(); // Initalisierung des Klassensystems! void InitClassSystem(); // Überprüft ob wir keinen ungültigen wert setzen für die Klassenvariablen: void CheckAllClassConVars(); // Hier wird geprüft ob wir die Klasse gewechselt haben: void OnClassChange(); // Setzt Leben und Armor für den Spieler! void SetClassStuff(); // Setzt den neuen wert für die Check Variable: void SetCurrentClassValue(); // Die Klasse holen: int GetClassValue()const; // Die Standartklasse holen: int GetDefaultClassValue()const; // Schaltmethode die Klassen verteilt: void SetPlayerClass(); // Legt das Leben für unsere klasse fest: int GetClassHealth()const; // Diese Methoden setzen für jede Klasse das Leben und die Armor int GetClassMaxHealth()const; // Legt die Armor für die Klasse Fest: int GetClassArmor()const; // Diese Methoden holen für jede Klasse das Leben und die Armor int GetClassMaxArmor()const; private: // Wichtige Prüfung auf ersten Spawn: bool m_bFirstSpawn; bool IsFirstSpawn(); // Welche Klasse haben wir(enum): int m_iClass; // Prüft ob wir die Klasse gewechselt haben: int m_iCurrentClass; // Hier setzen wir die Standartklasse! int m_iDefaultClass; // Waffen, Leben und Armor der Klassen verteilen: void SetClassDefault(); void SetClassGroundUnit(); void SetClassSupportUnit(); void SetClassMedic(); void SetHealthValue( int value );
/* ******************************************** **Spielereigenschaften: **Hier werden Eigenschaften wie Speed, Condition **und maximale Klassen festgelegt! ******************************************** */ // Integer für Rüstung: int m_iArmor; int m_iMaxArmor;
Nun zur Erklärung, von oben nach unten.
public
// Methode zum Klassenwechseln virtual void ChangeClass(int NewClass);
Diese Methode braucht man, damit der Client(Spieler) per Menu/Konsole seine Klasse wechselt.
virtual int GetClass();
Braucht man, wenn man noch Sachen wie Munition, Leben und Rüstungsinkrementierung für den Supporter/Medic einbauen will.
// Initalisierung des Klassensystems! void InitClassSystem();
Diese Methode soll das Klassensystem aus der Spawn Methode von CBasePlayer starten. Damit werden die Methoden für die Klassenverteilung usw aufgerufen. Bei der Implementierung ist man dann schlauer.
// Überprüft ob man keinen ungültigen wert setzt für die Klassenvariablen: void CheckAllClassConVars();
Diese Methode prüft, ob man einen gültigen Wert eingegeben hat. Falls wir das nicht Prüfen würden, dann würde eure Mod crashen! Falls der Wert nicht stimmt, dann müsst ihr einen Wert für die Klasse setzen.
// Hier wird geprüft ob man die Klasse gewechselt hat: void OnClassChange();
Diese Methode wird in der Thinkmethode gebraucht. Falls man die Klasse wechselt wird man gekillt und ein Punkt addiert sonst würde man Punktabzug bekommen.
// Setzt Leben und Armor für den Spieler! void SetClassStuff();
Diese Methode setzt für jede Klasse den Wert für das Leben, Maximal Leben und Rüstung. Leider wird die Rüstung über den Code der Recharger festgelegt, diesen muss man selber ändern.
// Setzt den neuen wert für die Check Variable: void SetCurrentClassValue();
Diese Methode ändert den Wert der CheckVariable für die Klassen, sonst würde man immer wieder sterben!
// Die Klasse holen: int GetClassValue()const;
Diese Methode holt den Wert der Klasse die man hat.
// Die Standartklasse holen: int GetDefaultClassValue()const;
Diese Methode holt vom Server die Standardklasse damit man im Falle einer ungültigen Klasse diese bekommt.
// Schaltmethode die Klassen verteilt: void SetPlayerClass();
Diese Methode ist die Steuerzentrale unseres Klassensystems. Dort wird mit dem Wert der Klassenvariable alles gelenkt. Von der Waffen und Lebensverteilung bis zum setzen des Spielermodels (Das muss man leider noch machen!).
// Legt das Leben für die Klasse fest: int GetClassHealth()const;
Diese Methode holt das Leben, das man im Moment hat.
// Diese Methoden setzt für jede Klasse das Leben und die Armor int GetClassMaxHealth()const;
Die Methode holt das Maximale Leben, das die Klasse haben kann.
// Legt die Armor für die Klasse Fest: int GetClassArmor()const;
Diese Methode holt die Rüstung, die man im Moment hat.
// Diese Methoden holt für jede Klasse das Leben und die Armor int GetClassMaxArmor()const;
Diese Methode holt die Maximale Rüstung der Klasse (ist leider noch unbrauchbar wegen dem Recharger Code!)
private
// Wichtige Prüfung auf ersten Spawn: bool m_bFirstSpawn;
Diese Variable ist für die Abfrage für den ersten Spawn nötig.
bool IsFirstSpawn();
Diese Methode gibt Auskunft ob man das Erste mal gespawnt wird.
// Welche Klasse hat man(enum): int m_iClass;
Diese Variable speichert den Wert der Klasse:
// Prüft, ob man die Klasse gewechselt hat: int m_iCurrentClass;
Das ist die Prüfungsvariable, die den Wert der Momentanen Klasse enthält. Der Wert wird dann geändert wenn die Klasse gewechselt wird.
// Hier setzt man die Standardklasse! int m_iDefaultClass;
Diese Variable holt die Klasse des Servers und ist gleichzeitig die erste Klasse, die man beim ersten Spawn bekommt.
// Waffen, Leben und Armor der Klassen verteilen: void SetClassDefault(); void SetClassGroundUnit(); void SetClassSupportUnit(); void SetClassMedic();
Das sind die Methoden zum verteilen aller wichtigen Sachen einer Klasse. (Leben, Maximalleben, Rüstung, Maximalrüstung, Waffen usw.)
// Integer für Rüstung: int m_iArmor; int m_iMaxArmor;
Das sind die Variablen für Rüstung und Maximalrüstung.
Jetzt wei0 man was man alles braucht und wieso.
Nun kommt man zum Teil in dem man alles Einbaut.
Die Implementation
Da man nun alles hat was man braucht muss man nurnoch alles einbauen! Alles kommt in die player.cpp ganz ans Ende.
Hier der Code mit Erklärung:
Added im Konstruktor:
// Erster Spawn? m_bFirstSpawn = true; // Startklasse festlegen: m_iClass = default_class.GetInt(); m_iCurrentClass = m_iClass; // Die Standardklasse setzen! m_iDefaultClass = default_class.GetInt(); // Standartwerte 100 für Leben/Armor: m_iHealth = 100; m_iArmor = 100; // Maximal Leben/Armor für jede Klasse: m_iMaxHealth = 100; m_iMaxArmor = 100;
void CBasePlayer::InitClassSystem() { DevMsg("Klassensystem wird initalisiert!\n"); CheckAllClassConVars(); SetPlayerClass(); SetClassStuff(); } int CBasePlayer::GetClassValue()const { return m_iClass; } int CBasePlayer::GetDefaultClassValue()const { return m_iDefaultClass; } bool CBasePlayer::IsFirstSpawn() { return m_bFirstSpawn; } // Soll die Waffen verteilen: // Hier ist irgend wo ein Bug! void CBasePlayer::SetPlayerClass() { if(IsFirstSpawn()) { m_iClass = m_iDefaultClass; } // Jetzt werden die Klassen verteilt: switch(m_iClass) { case Assaulter: SetClassGroundUnit(); break; case Supporter: SetClassSupportUnit(); break; case Medic: SetClassMedic(); break; //case Invalid: // Muss noch eingebaut werden! // Hier bekommt man nur die Standardwaffen! case Unassigned: // Hier setzt man die Standardklasse! default: SetClassDefault(); break; } } void CBasePlayer::OnClassChange() { if( m_iClass != m_iCurrentClass ) { // Spieler killen und Punkte um 1 erhöhen (wegen Selbstmord)! CommitSuicide(); IncrementFragCount(1); // Setzen, damit man nicht die selbe Klasse hat! m_iCurrentClass = m_iClass; } } void CBasePlayer::CheckAllClassConVars() { // Hat man eine Klasse, die zwischen Spec-Ops und der letzen Klasse liegt? if( m_iClass < Assaulter || m_iClass > Medic ) { m_iClass = Assaulter; } if( m_iDefaultClass < Assaulter || m_iDefaultClass > Medic ) { m_iDefaultClass = Assaulter; } } void CBasePlayer::SetClassDefault() { Msg("Du hast die Klasse Default!\n"); CheckAllClassConVars(); SetPlayerClass(); } // Assault: void CBasePlayer::SetClassGroundUnit() { // Standardwerte für Leben/Armor: m_iHealth = 125; m_iArmor = 125; // Maximal Leben/Armor für jede Klasse: m_iMaxHealth = 125; m_iMaxArmor = 125; // Waffen verteilen: Msg("Du bist jetzt eine Ground Unit!\n"); CBasePlayer::GiveNamedItem( "weapon_357" ); CBasePlayer::GiveNamedItem( "weapon_smg1" ); CBasePlayer::GiveNamedItem( "weapon_frag" ); CBasePlayer::GiveAmmo( Magazin_357*3 , "357" ); CBasePlayer::GiveAmmo( Magazin_SMG1*3 , "SMG1"); CBasePlayer::GiveAmmo( Magazin_SMG1_Granates*1, "smg1_grenade"); CBasePlayer::GiveAmmo( Magazin_Frag*5 , "grenade" ); } // Supporter void CBasePlayer::SetClassSupportUnit() { // Standartwerte für leben/armor: m_iHealth = 100; m_iArmor = 300; // Maximal Leben/Armor für Klasse: m_iMaxHealth = 100; m_iMaxArmor = 300; // Waffen verteilen: Msg("Du bist jetzt eine Support Unit!\n"); CBasePlayer::GiveNamedItem( "weapon_ar2" ); CBasePlayer::GiveNamedItem( "weapon_frag" ); CBasePlayer::GiveNamedItem( "weapon_357" ); CBasePlayer::GiveAmmo( Magazin_AR2*3, "AR2" ); CBasePlayer::GiveAmmo( Magazin_AR2AltFire*2, "AR2AltFire" ); CBasePlayer::GiveAmmo( Magazin_Frag*3, "grenade" ); CBasePlayer::GiveAmmo( Magazin_357*3 , "357" ); // Eigenschaft des Supporter's aufrufen: // GetAmmo(); } // Medic: void CBasePlayer::SetClassMedic() { // Standardwerte für Leben/Armor: m_iHealth = 100; m_iArmor = 75; // Maximal Leben/Armor für Klasse: m_iMaxHealth = 100; m_iMaxArmor = 75; // Waffen verteilen: Msg("Du bist jetzt ein Medic!\n"); CBasePlayer::GiveNamedItem( "weapon_357" ); CBasePlayer::GiveNamedItem( "weapon_smg1" ); CBasePlayer::GiveAmmo( Magazin_357*2, "357" ); CBasePlayer::GiveAmmo( Magazin_SMG1*2 , "SMG1"); CBasePlayer::GiveAmmo( Magazin_SMG1_Granates*3, "smg1_grenade"); } // Legt das Leben für die Klasse fest: int CBasePlayer::GetClassHealth()const { return m_iHealth; } // Legt die Armor für die Klasse fest: int CBasePlayer::GetClassArmor()const { return m_iArmor; } // Diese Methoden setzen für jede Klasse das Leben und die Armor int CBasePlayer::GetClassMaxHealth()const { return m_iMaxHealth; } // Diese Methoden holen für jede Klasse das Leben und die Armor int CBasePlayer::GetClassMaxArmor()const { return m_iMaxArmor; } // Setzt Leben und Armor für den Spieler! void CBasePlayer::SetClassStuff() { // Hier Leben setzen: SetHealthValue(GetClassHealth()); SetMaxHealthValue(GetClassMaxHealth()); // Variable gehört nicht zu CBasePlayer!!! // TODO: Das ist eine Private Variable, die ich ändern muss! SetArmorValue(GetClassArmor()); // SetMaxArmorValue(GetClassMaxArmor()); } // Klasse per ConVar Wechsel für Client: void CBasePlayer::ChangeClass(int NewClass) { m_iClass = NewClass; }
Da man ja schon weiß, wofür die ganzen Methoden sind, man nurnoch schauen wie alles läuft :)
Aber nun mal zum Einbauen der ConVars, die man braucht:
// Der Server hat für alle die selbe Standardklasse! // Der Admin kann die Standartklasse ändern! ConVar default_class("default_class", "3", FCVAR_ARCHIVE, "Variable für Standardklasse!");
Nun hat der Server seine Default-Klasse, die jeder Spieler beim Spawnen bekommt. Diese kann man dann über die Konsole ändern :)
Man kann auch noch mehr Settings für den Admin zur Verfügung stellen:
// Maximale Klassen erlauben(Admins!) // TODO: Muss noch aktiviert werden im Code! ConVar max_assaulter("max_assaulter", "3", FCVAR_ARCHIVE, "Variable für Maximale Assaulter!"); ConVar max_supporter("max_supporter", "3", FCVAR_ARCHIVE, "Variable für Maximale Supporter!"); ConVar max_medic("max_medic", "3", FCVAR_ARCHIVE, "Variable für Maximale Medics!");
// Klassen erlauben(Admins): // TODO: Muss noch aktiviert werden im Code! ConVar allow_assaulter("allow_assaulter", "1", FCVAR_ARCHIVE, "Erlaubt Klasse Ground Unit!"); ConVar allow_supporter("allow_supporter", "1", FCVAR_ARCHIVE, "Erlaubt Klasse Support Unit!"); ConVar allow_medic("allow_medic", "1", FCVAR_ARCHIVE, "Erlaubt Klasse Medic!");
Diese muss man aber selbst implementieren!
Nun muss man nur noch dem Spieler die Möglichkeit zum Ändern der Klasse geben! Und dann muss man noch die Prüfungen der Klassen einbauen!
Dazu muss man einfach in der Methode OnClientCommand folgendes am Ende einbauen:
else if ( !stricmp( cmd, "class" ) ) { if ( engine->Cmd_Argc() < 2 ) return true; int iClass = atoi( engine->Cmd_Argv(1) ); ChangeClass(iClass); return true; }
Hiermit wird eine ConVar simuliert. Aber man kann durch Class und dann die Klassennummer, also Class 1, die Klasse ändern! Nun muss man aber die Prüfungsmethode aufrufen und dann hat man es schon!
Das macht man in der Methode PostThink();
Dort setzt man am Ende einfach folgendes ein:
OnClassChange();
Das wars :) wenn alles stimmt dann dürfte das Klassensystem funktionieren ;)
Wichtiges zum Code
Damit der Code ohne Probleme läuft, muss man noch einiges fixen!
Erstmal muss man noch folgende Methoden im Public-bereich hinzufügen:
// Deklarationen: // Added von mir: void SetHealthValue( int value ); int GetHealthValue(); void SetMaxHealthValue(int MaxValue); int GetMaxHealthValue(); void IncrementHealthValue( int nCount ); int GetArmorValue();
// Implementierung: void CBasePlayer::SetHealthValue( int value ) { m_iHealth = value; } void CBasePlayer::SetMaxHealthValue( int MaxValue ) { m_iMaxHealth = MaxValue; } int CBasePlayer::GetHealthValue() { return m_iHealth; } int CBasePlayer::GetMaxHealthValue() { return m_iMaxHealth; } void CBasePlayer::IncrementHealthValue( int nCount ) { m_iHealth += nCount; if (m_iMaxHealth > 0 && m_iHealth > m_iMaxHealth) m_iHealth = m_iMaxHealth; } int CBasePlayer::GetArmorValue() { return m_ArmorValue; }
Damit kann man die Armor und das Health setzen (je nachdem, wieviel die Klassen haben sollen). Aber auch Medic und Supporter können so ihr Leben/Rüstung regenerieren!
Nun muss man noch die Munitionsverteilung ändern. Entweder man gibt die Munitionszahlen selber ein oder man erstellt eine Header wie folgt: Header definition starten:
#ifndef _Magazin_H #define _Magazin_H
Die Magazinsdefinitionen:
// Nur verändern, wenn man die Munition der Waffenmagazine im script/code ändert! // Legt die Magazine fest(Magazin und dann größe in Kugeln)! #define Magazin_None 0 #define Magazin_Pistole 20 #define Magazin_357 6 #define Magazin_SMG1 50 #define Magazin_SMG1_Granates 1 #define Magazin_AR2 100 #define Magazin_AR2AltFire 1 #define Magazin_RPG 1 #define Magazin_Slam 1 #define Magazin_Frag 1 #define Magazin_Shotgun 8 #define Magazin_Crossbow 1
Die maximale Definition eines Magazins:
// Legt die Mazimale Muntion/Magazine fest: #define Max_Magazin_None Magazin_None*0 #define Max_Magazin_Pistole Magazin_Pistole*16 #define Max_Magazin_357 Magazin_357*6 #define Max_Magazin_SMG1 Magazin_SMG1*8 #define Max_Magazin_SMG1_Granates Magazin_SMG1_Granates*7 #define Max_Magazin_AR2 Magazin_AR2*3 #define Max_Magazin_AR2AltFire Magazin_AR2AltFire*2 #define Max_Magazin_RPG Magazin_RPG*25 #define Max_Magazin_Slam Magazin_Slam*10 #define Max_Magazin_Frag Magazin_Frag*10 #define Max_Magazin_Shotgun Magazin_Shotgun*13 #define Max_Magazin_Crossbow Magazin_Crossbow*50
Die Magazinsdefinition beenden:
#endif //_Magazin_H
Ich würde zur zweiten Methode raten, da man hier auch die Munitionsdefinitions in den gamerules.cpp ändern kann und die maximale Munition einbinden kann!
Und man sollte die Default Klasse per CooVars setzen oder die Default Klasse aus dem Coden komplett entfernen!
Damit man das Klassen system später aufrufen kann, solte man in der baseviewport.cpp dieses eintragen:
// sub dialogs #include "clientscoreboarddialog.h" #include "spectatorgui.h" #include "teammenu.h" #include "classmenu.h" #include "vguitextwindow.h" #include "IGameUIFuncs.h" #include "mapoverview.h" #include "hud.h" #include "NavProgress.h"
Jetzt den Befehl zum Aufrufen:
CON_COMMAND( chooseclass, "Opens a menu for class choose" ) { if ( !gViewPortInterface ) return; gViewPortInterface->ShowPanel( "class", true ); }
Etwas weiter unten das hier:
void CBaseViewport::CreateDefaultPanels( void ) { #ifndef _XBOX AddNewPanel( CreatePanelByName( PANEL_SCOREBOARD ) ); AddNewPanel( CreatePanelByName( PANEL_INFO ) ); AddNewPanel( CreatePanelByName( PANEL_SPECGUI ) ); AddNewPanel( CreatePanelByName( PANEL_SPECMENU ) ); AddNewPanel( CreatePanelByName( PANEL_NAV_PROGRESS ) ); AddNewPanel( CreatePanelByName( PANEL_TEAM ) ); AddNewPanel( CreatePanelByName( PANEL_CLASS ) ); // AddNewPanel( CreatePanelByName( PANEL_BUY ) ); #endif }
Und zuletzt das hier:
IViewPortPanel* CBaseViewport::CreatePanelByName(const char *szPanelName) { ... else if ( Q_strcmp(PANEL_TEAM, szPanelName) == 0 ) { newpanel = new CTeamMenu( this ); } else if ( Q_strcmp(PANEL_CLASS, szPanelName) == 0 ) { newpanel = new CTeamMenu( this ); } ... }
Bonus
Nun kann man sich noch einen Spaß erlauben und jeder Klasse eine bestimmte Geschwindigkeit zuweisen.
Dazu braucht man die hl2_player.cpp und die player.h/.cpp
Als erstes muss man ausfindig machen, wo der Spieler seine Laufgeschwindigkeit einstellt!
Das macht man hier:
#ifdef HL2MP #define HL2_WALK_SPEED 150 #define HL2_NORM_SPEED 190 #define HL2_SPRINT_SPEED 320 #else #define HL2_WALK_SPEED hl2_walkspeed.GetFloat() #define HL2_NORM_SPEED hl2_normspeed.GetFloat() #define HL2_SPRINT_SPEED hl2_sprintspeed.GetFloat() #endif
Die Erklärung ist simpel. Wenn HL2MP definiert ist, dann werden Standardwerte gesetzt:
#ifdef HL2MP #define HL2_WALK_SPEED 150 #define HL2_NORM_SPEED 190 #define HL2_SPRINT_SPEED 320
Ansonsten kann man alles über die ConVars machen, aber in HL2DM geht das nur über die Standardwerte!
#else #define HL2_WALK_SPEED hl2_walkspeed.GetFloat() #define HL2_NORM_SPEED hl2_normspeed.GetFloat() #define HL2_SPRINT_SPEED hl2_sprintspeed.GetFloat() #endif
Aber nun muss man eine Steuerung bauen für den Speed!
Dazu muss man nur eine Kleinigkeit zum Basisspieler hinzufügen. player.h öffnen und folgendes im letzten Public-bereich hinzufügen:
// Hier wird die Spielergeschwindigkeit gesetzt: void SetWalkSpeed(int WalkSpeed); void SetNormSpeed(int NormSpeed); void SetSprintSpeed(int SprintSpeed);
Damit kann man die Werte setzen, aber nun braucht man noch die Variablen der Klasse:
// Spielergeschwindigkeit: int m_iWalkSpeed; int m_iNormSpeed; int m_iSprintSpeed;
Nun noch die Methoden zum holen der Werte:
int GetWalkSpeed(); int GetNormSpeed(); int GetSprintSpeed();
Jetzt zur Implementierung:
void CBasePlayer::SetWalkSpeed(int WalkSpeed) { m_iWalkSpeed=WalkSpeed; } void CBasePlayer::SetNormSpeed(int NormSpeed) { m_iNormSpeed=NormSpeed; } void CBasePlayer::SetSprintSpeed(int SprintSpeed) { m_iSprintSpeed=SprintSpeed; } int CBasePlayer::GetWalkSpeed() { return m_iWalkSpeed; } int CBasePlayer::GetNormSpeed() { return m_iNormSpeed; } int CBasePlayer::GetSprintSpeed() { return m_iSprintSpeed; }
Jetzt muss man nur noch 2 Sachen tun!
Als erstes muss man sagen, dass die Get Methoden die Geschwindigkeit steuern.
Das macht man wie folgt:
#define HL2_WALK_SPEED CBasePlayer::GetWalkSpeed() #define HL2_NORM_SPEED CBasePlayer::GetNormSpeed() #define HL2_SPRINT_SPEED CBasePlayer::GetSprintSpeed()
Das wars auch schon fast.
Jetzt muss man nurnoch definieren welche Geschwindigkeit eure Klasse haben soll.
Dazu mmuss man nur in den SetClass Methoden die neuen SetSpeed Methoden einbauen.
Dann kann man eine Klasse schnell einbauen.
Hier mal ein Beispiel meiner Supportunit-Klasse:
// Supporter
void CBasePlayer::SetClassSupportUnit()
{
// Code hier rein!
// m_szClassName = ClassNames[CLASS_SUPPORT];
// Standartwerte für leben/armor:
m_iHealth = 100;
m_iArmor = 300;
// Maximal Leben/Armor für Jede Klasse:
m_iMaxHealth = 100;
m_iMaxArmor = 300;
// Waffen verteilen:
Msg("Du bist jetzt eine Support Unit!\n");
switch(GetTeamNumber())
{
case TEAM_REBELS:
// Hier waffenverteilen:
// Rebelen:
CBasePlayer::GiveNamedItem( "weapon_reb_hmg" );
CBasePlayer::GiveNamedItem( "weapon_reb_frag" );
break;
case TEAM_COMBINE:
// Hier waffenverteilen:
// Combine:
CBasePlayer::GiveNamedItem( "weapon_com_hmg" );
CBasePlayer::GiveNamedItem( "weapon_com_frag" );
break;
default:
CBasePlayer::GiveNamedItem( "weapon_ar2" );
CBasePlayer::GiveNamedItem( "weapon_frag" );
break;
}
CBasePlayer::GiveNamedItem( "weapon_ammo_spawner" );
CBasePlayer::GiveAmmo( Magazin_AR2*3, "AR2" );
CBasePlayer::GiveAmmo( Magazin_Frag*3, "grenade" );
SetWalkSpeed(90);
SetNormSpeed(130);
SetSprintSpeed(200);
}
Ich habe auch schon die Waffenverteilung auf die Teams gesetzt aber das kann ich auch noch erklären ;) Sobald ich das verbessert hab (z.b. mit einer Team-Variable) ;)
Also viel Spaß und schreibt mir falls es Probleme oder Kritik gibt ;)