TUTORIAL 7 - Cloaking
von AssKicka
Dieses mal ärgern wir die Bots ein wenig, so wie es der
Predator tut. Wir bauen ein nettes Unsichtbarkeits-Feature ein, das allerdings
während
der Benutzung dem Spieler Health abzieht.
1. NEUES ENTITY FLAG HINZUFÜGEN
Als erstes werden wir ein neues Entity Flag names FL_CLOAK hinzufügen, mit
dem wir jeweils unsere Unsichtbarkeit ein- und ausschalten können. Öffne
die Datei g_local.h, und füge folgende Zeile zu den gentity->flags
hinzu:
#define FL_CLOAK 0x00020000 //
health cloaking
(Eventuell müsst ihr einen anderen Wert als 0x00020000 nehmen,
falls ihr den schon für andere Zwecke verwendet.)
2. NEUEN CONSOLENBEFEHL EINFÜHREN
Öffne die Datei g_cmds.c und füge vor den ClientCommands folgende Funktion
ein:
/*
=================
Cmd_Cloak_f
=================
*/
void Cmd_Cloak_f( gentity_t *ent ) {
char *msg; // message to player
ent->flags ^= FL_CLOAK;
if (!(ent->flags & FL_CLOAK))
{
msg = "Cloaking OFF\n";
ent->client->ps.powerups[PW_INVIS] = level.time;
// Removes the invisible powerup from the player
} else {
msg = "Cloaking ON\n";
ent->client->ps.powerups[PW_INVIS] = level.time + 1000000000;
// Gives the invisible powerup to the player
}
trap_SendServerCommand( ent-g_entities, va("print \"%s\"",
msg));
Hier haben wir eine Funktion erstellt, die durch das \cloak Kommando über
die Konsole aufgerufen wird. Die Implementierung zum Erkennen der Eingabe
in der Konsole folgt gleich. Die obige Funktion ändert den Status des Flags
FL_CLOAK durch die XOR Verknüpfung, schaltet die Unsichtbarkeit an oder
aus, und schreibt eine entsprechende "an" oder "aus" Meldung an den Spieler.
Aber was zum Teufel soll das "level.time + 1000000000"? Damit
setzen wir die theoretische Dauer des Unsichtbarkeits-Powerups auf eine Zeit
von 1666 Minuten. Wir werden dieses Powerup nicht wirklich so lange aktiviert
haben, denn wir werden die Health des Spielers kontinuierlich vermindern,
und ab nur noch 10 Health automatisch die Unsichtbarkeit deaktivieren.
Jetzt implementieren wir das Erkennen des Aufrufes "cloak" in
der Konsole. Wir fügen weiter unten in g_cmds.c, ein weiteres else if an:
else if (Q_stricmp (cmd, "cloak") == 0)
Cmd_Cloak_f( ent );
3. HEALTH DES SPIELERS WÄHREND DER UNSICHTBARKEIT VERMINDERN
Solange das Unsichtbarkeits-Powerup aktiviert ist, wollen wir jede Sekunde
die Health des Players vermindern. Öffne dazu g_active.c und gehe in den
Bereich "ClientTimerActions". Die Funktion ClientTimerActions() wird genau
einmal in der Sekunde aufgerufen, eignet sich also perfekt für unsere Zwecke.
Wir suchen folgenden Abschnitt:
// count down health when over max
if ( ent->health > client->ps.stats[STAT_MAX_HEALTH]
) {
}
und ändern diesen in den Folgenden um:
if (!(ent->flags & FL_CLOAK)) {
// count down health when over max and not cloaked.
if ( ent->health > client->ps.stats[STAT_MAX_HEALTH] ) {
}
// count down health when cloaked.
ent->health--;
if ( ent->health < 11) {
ent->flags ^= FL_CLOAK;
ent->client->ps.powerups[PW_INVIS] = level.time;
}
Schauen wir uns näher an, was wir hier getan haben. Als erstes überprüfen
wir, ob FL_CLOAK aktiviert (also das Flag gesetzt) ist, wenn es NICHT gesetzt
ist, überprüfen wir, ob die Health des Spielers größer als 100 (STAT_MAX_HEALTH)
ist. Tritt dieser Fall ein, so vermindern wir die Health des Spielers,
wie vom Original gewohnt. Wenn der Player unsichtbar ist (also FL_CLOAK
gesetzt), so wird der else Teil ausgeführt,
wodurch auch die Health des Spielers vermindert wird. Der Grund für diese
etwas umständlichere Abfrage ist, dass wir nicht wollen, das dem Spieler
gleich 2 Health Punkte pro Sekunde abgezogen werden, falls er unsichtbar
ist UND über 100 Health hat. Zudem haben wir die automatische Abfrage eingebaut,
die bei weniger als 11 Health die Unsichtbarkeit deaktiviert.
4. KEINE POWER-UPS WEGWERFEN WENN MAN GEFRAGGT WIRD
Der nächste Schritt ist es, das Unsichtbarkeits-Powerup zu entfernen, kurz
bevor die normalen Powerups vom Spieler weggeschmissen werden, wenn er
stirbt. Das brauchen wir, denn würde der Spieler sterben, während er unsichtbar
ist, so würde er das Invisible-Powerup neben sich liegen lassen, und der
nächste könnte dieses unendlich lange ohne Verminderung der Health benutzen
(was doch ein wenig unfair wäre).
Also gehen wir nun in g_combat.c in den Bereich TossClientItems.
Dort gibt es den Unterbereich markiert mit:
// drop all the powerups if not
in teamplay
In den Block der darunterliegenden if-Abfrage fügen wir gleich
am Anfang folgendes ein:
if (self->flags & FL_CLOAK) {
// remove the invisible powerup if the player is cloaked.
self->client->ps.powerups[PW_INVIS] = level.time;
}
Das wars auch schon, nun einfach kompilieren und die Änderungen
an den ahnungslosen Bots ausprobieren :-).
|